pyroscope.write
pyroscope.write receives performance profiles from other components and forwards them to a series of user-supplied endpoints.
When pyroscope.write forwards profiles, all labels starting with double underscore (__) are dropped before the data is sent, with the following exceptions:
__name__is preserved because it identifies the profile type.__delta__is preserved because it’s required for delta profiles.
You can specify multiple pyroscope.write components by giving them different labels.
Usage
pyroscope.write "<LABEL>" {
endpoint {
url = "<PYROSCOPE_URL>"
...
}
...
}Arguments
You can use the following argument with pyroscope.write:
| Name | Type | Description | Default | Required |
|---|---|---|---|---|
external_labels | map(string) | Labels to add to profiles sent over the network. | no |
Blocks
You can use the following blocks with pyroscope.write:
| Block | Description | Required |
|---|---|---|
endpoint | Location to send profiles to. | no |
endpoint > authorization | Configure generic authorization to the endpoint. | no |
endpoint > basic_auth | Configure basic_auth for authenticating to the endpoint. | no |
endpoint > oauth2 | Configure OAuth 2.0 for authenticating to the endpoint. | no |
endpoint > oauth2 > tls_config | Configure TLS settings for connecting to the endpoint. | no |
endpoint > tls_config | Configure TLS settings for connecting to the endpoint. | no |
The > symbol indicates deeper levels of nesting.
For example, endpoint > basic_auth refers to a basic_auth block defined inside an endpoint block.
endpoint
The endpoint block describes a single location to send profiles to.
Multiple endpoint blocks can be provided to send profiles to multiple locations.
The following arguments are supported:
| Name | Type | Description | Default | Required |
|---|---|---|---|---|
url | string | Full URL to send metrics to. | yes | |
bearer_token_file | string | File containing a bearer token to authenticate with. | no | |
bearer_token | secret | Bearer token to authenticate with. | no | |
enable_http2 | bool | Whether HTTP2 is supported for requests. | true | no |
follow_redirects | bool | Whether redirects returned by the server should be followed. | true | no |
headers | map(string) | Extra headers to deliver with the request. | no | |
http_headers | map(list(secret)) | Custom HTTP headers to be sent along with each request. The map key is the header name. | no | |
max_backoff_period | duration | Maximum backoff time between retries. | "5m" | no |
max_backoff_retries | int | Maximum number of retries. 0 to retry infinitely. | 10 | no |
min_backoff_period | duration | Initial backoff time between retries. | "500ms" | no |
name | string | Optional name to identify the endpoint in metrics. | no | |
no_proxy | string | Comma-separated list of IP addresses, CIDR notations, and domain names to exclude from proxying. | no | |
proxy_connect_header | map(list(secret)) | Specifies headers to send to proxies during CONNECT requests. | no | |
proxy_from_environment | bool | Use the proxy URL indicated by environment variables. | false | no |
proxy_url | string | HTTP proxy to send requests through. | no | |
remote_timeout | duration | Timeout for requests made to the URL. | "10s" | no |
At most, one of the following can be provided:
authorizationblockbasic_authblockbearer_token_fileargumentbearer_tokenargumentoauth2block
no_proxy can contain IPs, CIDR notations, and domain names. IP and domain names can contain port numbers.
proxy_url must be configured if no_proxy is configured.
proxy_from_environment uses the environment variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY (or the lowercase versions thereof).
Requests use the proxy from the environment variable matching their scheme, unless excluded by NO_PROXY.
proxy_url and no_proxy must not be configured if proxy_from_environment is configured.
proxy_connect_header should only be configured if proxy_url or proxy_from_environment are configured.
When you provide multiple endpoint blocks, profiles are concurrently forwarded to all configured locations.
authorization
| Name | Type | Description | Default | Required |
|---|---|---|---|---|
credentials_file | string | File containing the secret value. | no | |
credentials | secret | Secret value. | no | |
type | string | Authorization type, for example, “Bearer”. | no |
credential and credentials_file are mutually exclusive, and only one can be provided inside an authorization block.
Warning
Using
credentials_filecauses the file to be read on every outgoing request. Use thelocal.filecomponent with thecredentialsattribute instead to avoid unnecessary reads.
basic_auth
| Name | Type | Description | Default | Required |
|---|---|---|---|---|
password_file | string | File containing the basic auth password. | no | |
password | secret | Basic auth password. | no | |
username | string | Basic auth username. | no |
password and password_file are mutually exclusive, and only one can be provided inside a basic_auth block.
Warning
Using
password_filecauses the file to be read on every outgoing request. Use thelocal.filecomponent with thepasswordattribute instead to avoid unnecessary reads.
oauth2
| Name | Type | Description | Default | Required |
|---|---|---|---|---|
client_id | string | OAuth2 client ID. | no | |
client_secret_file | string | File containing the OAuth2 client secret. | no | |
client_secret | secret | OAuth2 client secret. | no | |
endpoint_params | map(string) | Optional parameters to append to the token URL. | no | |
no_proxy | string | Comma-separated list of IP addresses, CIDR notations, and domain names to exclude from proxying. | no | |
proxy_connect_header | map(list(secret)) | Specifies headers to send to proxies during CONNECT requests. | no | |
proxy_from_environment | bool | Use the proxy URL indicated by environment variables. | false | no |
proxy_url | string | HTTP proxy to send requests through. | no | |
scopes | list(string) | List of scopes to authenticate with. | no | |
token_url | string | URL to fetch the token from. | no |
client_secret and client_secret_file are mutually exclusive, and only one can be provided inside an oauth2 block.
Warning
Using
client_secret_filecauses the file to be read on every outgoing request. Use thelocal.filecomponent with theclient_secretattribute instead to avoid unnecessary reads.
The oauth2 block may also contain a separate tls_config sub-block.
no_proxy can contain IPs, CIDR notations, and domain names. IP and domain names can contain port numbers.
proxy_url must be configured if no_proxy is configured.
proxy_from_environment uses the environment variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY (or the lowercase versions thereof).
Requests use the proxy from the environment variable matching their scheme, unless excluded by NO_PROXY.
proxy_url and no_proxy must not be configured if proxy_from_environment is configured.
proxy_connect_header should only be configured if proxy_url or proxy_from_environment are configured.
tls_config
| Name | Type | Description | Default | Required |
|---|---|---|---|---|
ca_pem | string | CA PEM-encoded text to validate the server with. | no | |
ca_file | string | CA certificate to validate the server with. | no | |
cert_pem | string | Certificate PEM-encoded text for client authentication. | no | |
cert_file | string | Certificate file for client authentication. | no | |
insecure_skip_verify | bool | Disables validation of the server certificate. | no | |
key_file | string | Key file for client authentication. | no | |
key_pem | secret | Key PEM-encoded text for client authentication. | no | |
min_version | string | Minimum acceptable TLS version. | no | |
server_name | string | ServerName extension to indicate the name of the server. | no |
The following pairs of arguments are mutually exclusive and can’t both be set simultaneously:
ca_pemandca_filecert_pemandcert_filekey_pemandkey_file
When configuring client authentication, both the client certificate (using cert_pem or cert_file) and the client key (using key_pem or key_file) must be provided.
When min_version isn’t provided, the minimum acceptable TLS version is inherited from Go’s default minimum version, TLS 1.2.
If min_version is provided, it must be set to one of the following strings:
"TLS10"(TLS 1.0)"TLS11"(TLS 1.1)"TLS12"(TLS 1.2)"TLS13"(TLS 1.3)
Exported fields
The following fields are exported and can be referenced by other components:
| Name | Type | Description |
|---|---|---|
receiver | receiver | A value that other components can use to send profiles to. |
Component health
pyroscope.write is only reported as unhealthy if given an invalid configuration.
In those cases, exported fields are kept at their last healthy values.
Debug information
pyroscope.write doesn’t expose any component-specific debug information.
Metrics
pyroscope.write exposes the following metrics:
| Metric | Type | Description |
|---|---|---|
pyroscope_write_sent_bytes_total | Counter | Total number of compressed bytes sent to Pyroscope endpoints. |
pyroscope_write_dropped_bytes_total | Counter | Total number of compressed bytes dropped by Pyroscope endpoints. |
pyroscope_write_sent_profiles_total | Counter | Total number of profiles sent to Pyroscope endpoints. |
pyroscope_write_dropped_profiles_total | Counter | Total number of profiles dropped by Pyroscope endpoints. |
pyroscope_write_retries_total | Counter | Total number of retries to Pyroscope endpoints. |
pyroscope_write_latency | Histogram | Write latency for sending profiles to Pyroscope endpoints. |
All metrics include an endpoint label identifying the specific endpoint URL. The pyroscope_write_latency metric includes an additional type label with the following values:
push_total: Total latency for push operationspush_endpoint: Per-endpoint latency for push operationspush_downstream: Downstream request latency for push operationsingest_total: Total latency for ingest operationsingest_endpoint: Per-endpoint latency for ingest operationsingest_downstream: Downstream request latency for ingest operations
Troubleshoot
Connection limit errors
When using pyroscope.write to push profiles to a pyroscope.receive_http component, you may encounter errors like:
"failed to push to endpoint" err="deadline_exceeded: context deadline exceeded"This typically indicates that the receiving component has reached its TCP connection limit.
To resolve connection limit errors, first diagnose the issue, then apply one of the solutions.
Diagnose connection limit issues
Check the connection metrics on the
pyroscope.receive_httpcomponent:pyroscope_receive_http_tcp_connections: Current number of accepted TCP connectionspyroscope_receive_http_tcp_connections_limit: Maximum number of TCP connections allowed
If the current connections are approaching or at the limit, you need to take action.
Solution 1: Increase the connection limit
To increase the connection limit, increase the conn_limit parameter in the pyroscope.receive_http configuration:
pyroscope.receive_http "example" {
http {
conn_limit = 32768 // Increase from default 16384
// ... other settings
}
// ... rest of configuration
}Solution 2: Horizontal scaling
To distribute the connection load across multiple receivers, deploy multiple instances of pyroscope.receive_http behind a load balancer.
Timeout chain issues
When chaining multiple Pyroscope components such as pyroscope.write to pyroscope.receive_http to another pyroscope.write, you may encounter timeout issues that prevent retries:
"failed to push to endpoint" err="deadline_exceeded: context deadline exceeded"Understand the problem
This issue occurs when:
- The first
pyroscope.writecomponent sends profiles topyroscope.receive_http. - The
pyroscope.receive_httpcomponent forwards profiles to anotherpyroscope.writecomponent. - Both
pyroscope.writecomponents have the same defaultremote_timeoutof 10 seconds. - The request context passes from the first
pyroscope.writethroughpyroscope.receive_httpto the secondpyroscope.write, maintaining the original 10-second deadline. - If the second
pyroscope.writecomponent’s downstream request takes the full 10 seconds due to a broken TCP idle connection, there’s no time left for retries.
To resolve timeout chain issues, apply one of the following solutions.
Solution 1: Increase timeout on the first pyroscope.write
To provide buffer time for retries, increase the remote_timeout on the initial pyroscope.write component:
pyroscope.write "w1" {
endpoint {
url = "http://pyroscope-receiver:8080"
remote_timeout = "30s" // Increased from default 10s
// ... other settings
}
// ... rest of configuration
}Solution 2: Decrease timeout on the downstream pyroscope.write
To ensure faster failures and allow time for retries, reduce the remote_timeout on the downstream pyroscope.write component:
pyroscope.write "w2" {
endpoint {
url = "http://pyroscope-backend:4040"
remote_timeout = "3s" // Reduced from default 10s
// ... other settings
}
// ... rest of configuration
}Important considerations
- Normal latency: Pyroscope servers with the new architecture typically have 500-1000ms average latency for requests
- Timeout buffer: Always leave sufficient buffer time for retries when chaining components
- Retry configuration: Consider adjusting
max_backoff_retriesand backoff periods alongside timeout values - Monitoring: Monitor the
pyroscope_write_latencymetric to understand actual request latencies and adjust timeouts accordingly
Example
pyroscope.write "staging" {
// Send metrics to a locally running Pyroscope instance.
endpoint {
url = "http://pyroscope:4040"
headers = {
"X-Scope-OrgID" = "squad-1",
}
}
external_labels = {
"env" = "staging",
}
}
pyroscope.scrape "default" {
targets = [
{"__address__" = "pyroscope:4040", "service_name"="pyroscope"},
{"__address__" = "alloy:12345", "service_name"="alloy"},
]
forward_to = [pyroscope.write.staging.receiver]
}Compatible components
pyroscope.write has exports that can be consumed by the following components:
- Components that consume Pyroscope
ProfilesReceiver
Note
Connecting some components may not be sensible or components may require further configuration to make the connection work correctly. Refer to the linked documentation for more details.



