Tempo¶
Connect HolmesGPT to Tempo for distributed trace analysis. Useful for diagnosing performance issues like high latency, slow operations, and request failures across microservices.
When to Use This¶
- ✅ Your applications emit distributed traces to Tempo
- ✅ You need to debug latency or identify slow operations
- ✅ You want to correlate errors with specific traces
Prerequisites¶
- Tempo instance receiving traces from your applications
- Grafana with a Tempo datasource configured (recommended) OR direct Tempo API access
Configuration¶
HolmesGPT supports three ways to connect to Tempo. Pick the one that matches your setup:
| Setup | When to use |
|---|---|
| Self-Hosted Tempo via Grafana Proxy (recommended) | You run your own Grafana with a Tempo datasource configured |
| Self-Hosted Tempo - Direct Connection | Self-hosted Tempo without Grafana, including multi-tenant setups needing X-Scope-OrgID |
| Grafana Cloud | Your Grafana Cloud stack (queries Tempo via your Grafana Cloud Grafana) |
Self-Hosted Tempo via Grafana Proxy¶
HolmesGPT queries your self-hosted Tempo through your Grafana instance's datasource proxy. Recommended when you already have Grafana — it handles authentication and you only need one API key. This is also the only mode that produces clickable "View in Grafana" links in Holmes's responses.
Required:
- A Grafana service account token with:
- Basic role → Viewer
- Data sources → Reader
- Tempo datasource UID from Grafana
See this video for a walkthrough of creating the service account token.
Find your Tempo datasource UID:
# Port forward to Grafana
kubectl port-forward svc/robusta-grafana 3000:80
# Get Tempo datasource UID
curl -s -u <username>:<password> http://localhost:3000/api/datasources | jq '.[] | select(.type == "tempo") | .uid'
Set the environment variable:
Add the following to ~/.holmes/config.yaml. Create the file if it doesn't exist:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: <your grafana url> # e.g. http://grafana.monitoring.svc.cluster.local
api_key: "{{ env.GRAFANA_TEMPO_API_KEY }}"
grafana_datasource_uid: <the UID of the tempo data source in Grafana>
After making changes to your configuration, run:
To test, run:
Create a Kubernetes secret in the namespace Holmes runs in:
kubectl create secret generic holmes-grafanatempo \
--from-literal=GRAFANA_TEMPO_API_KEY=your-grafana-service-account-token \
-n <namespace>
When using the standalone Holmes Helm Chart, update your values.yaml:
extraEnvVarsSecrets:
- holmes-grafanatempo
toolsets:
grafana/tempo:
enabled: true
config:
api_url: <your grafana url> # e.g. http://grafana.monitoring.svc.cluster.local
api_key: "{{ env.GRAFANA_TEMPO_API_KEY }}"
grafana_datasource_uid: <the UID of the tempo data source in Grafana>
Apply the configuration:
Create a Kubernetes secret in the namespace Holmes runs in:
kubectl create secret generic holmes-grafanatempo \
--from-literal=GRAFANA_TEMPO_API_KEY=your-grafana-service-account-token \
-n <namespace>
When using the Robusta Helm Chart (which includes HolmesGPT), update your generated_values.yaml:
holmes:
extraEnvVarsSecrets:
- holmes-grafanatempo
toolsets:
grafana/tempo:
enabled: true
config:
api_url: <your grafana url> # e.g. http://grafana.monitoring.svc.cluster.local
api_key: "{{ env.GRAFANA_TEMPO_API_KEY }}"
grafana_datasource_uid: <the UID of the tempo data source in Grafana>
Apply the configuration:
Self-Hosted Tempo - Direct Connection¶
HolmesGPT connects directly to a self-hosted Tempo API endpoint without going through Grafana.
In Kubernetes, no secret is needed in this mode — direct Tempo connections don't carry an API key.
Add the following to ~/.holmes/config.yaml. Create the file if it doesn't exist:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: http://tempo.monitoring.svc.cluster.local:3200
additional_headers:
X-Scope-OrgID: "<tenant id>" # Only needed for multi-tenant Tempo
After making changes to your configuration, run:
When using the standalone Holmes Helm Chart, update your values.yaml:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: http://tempo.monitoring.svc.cluster.local:3200
additional_headers:
X-Scope-OrgID: "<tenant id>" # Only needed for multi-tenant Tempo
Apply the configuration:
When using the Robusta Helm Chart (which includes HolmesGPT), update your generated_values.yaml:
holmes:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: http://tempo.monitoring.svc.cluster.local:3200
additional_headers:
X-Scope-OrgID: "<tenant id>" # Only needed for multi-tenant Tempo
Apply the configuration:
Grafana Cloud¶
Query Tempo through your Grafana Cloud Grafana instance's datasource proxy. Same flow as the self-hosted proxy option, just pointed at your Grafana Cloud URL.
Required:
- Your Grafana Cloud Grafana URL (e.g.,
https://myorg.grafana.net) - A Grafana Cloud service account token with:
- Basic role → Viewer
- Data sources → Reader
- Tempo datasource UID from your Grafana Cloud Grafana
Find your Tempo datasource UID:
In your Grafana Cloud Grafana UI → Connections → Data sources → click on the Tempo datasource. The UID appears in the URL. Or via the API:
curl -s -H "Authorization: Bearer <service-account-token>" https://<your-stack>.grafana.net/api/datasources | jq '.[] | select(.type == "tempo") | .uid'
Set the environment variable:
Add the following to ~/.holmes/config.yaml. Create the file if it doesn't exist:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: https://<your-stack>.grafana.net
api_key: "{{ env.GRAFANA_CLOUD_TEMPO_API_KEY }}"
grafana_datasource_uid: <the UID of the Tempo datasource>
After making changes to your configuration, run:
Create a Kubernetes secret in the namespace Holmes runs in:
kubectl create secret generic holmes-grafanatempo-cloud \
--from-literal=GRAFANA_CLOUD_TEMPO_API_KEY=your-grafana-cloud-service-account-token \
-n <namespace>
When using the standalone Holmes Helm Chart, update your values.yaml:
extraEnvVarsSecrets:
- holmes-grafanatempo-cloud
toolsets:
grafana/tempo:
enabled: true
config:
api_url: https://<your-stack>.grafana.net
api_key: "{{ env.GRAFANA_CLOUD_TEMPO_API_KEY }}"
grafana_datasource_uid: <the UID of the Tempo datasource>
Apply the configuration:
Create a Kubernetes secret in the namespace Holmes runs in:
kubectl create secret generic holmes-grafanatempo-cloud \
--from-literal=GRAFANA_CLOUD_TEMPO_API_KEY=your-grafana-cloud-service-account-token \
-n <namespace>
When using the Robusta Helm Chart (which includes HolmesGPT), update your generated_values.yaml:
holmes:
extraEnvVarsSecrets:
- holmes-grafanatempo-cloud
toolsets:
grafana/tempo:
enabled: true
config:
api_url: https://<your-stack>.grafana.net
api_key: "{{ env.GRAFANA_CLOUD_TEMPO_API_KEY }}"
grafana_datasource_uid: <the UID of the Tempo datasource>
Apply the configuration:
Multiple Instances¶
The Grafana Tempo toolset can connect to more than one Grafana Tempo instance. List each one under instances: with a unique name. Any config field set outside instances: becomes a default that every instance inherits, so shared settings only need to be written once.
toolsets:
grafana/tempo:
enabled: true
config:
instances:
- name: prod
api_url: <your grafana url>
api_key: <your grafana service account token>
grafana_datasource_uid: <the UID of the Tempo datasource>
- name: staging
api_url: <your grafana url>
api_key: <your grafana service account token>
grafana_datasource_uid: <the UID of the Tempo datasource>
When more than one instance is configured, HolmesGPT automatically adds an instance parameter to every Grafana Tempo tool (so it can pick which instance to query) and a grafana_tempo_list_instances tool to list the configured instances. With a single instance — including the flat config without instances: — the tools are unchanged and fully backwards compatible.
See Multiple Instances for the full behaviour, including global defaults and health reporting.
Advanced Configuration¶
SSL Verification¶
For self-signed certificates, you can disable SSL verification:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: https://tempo.internal
verify_ssl: false # Disable SSL verification (default: true)
External URL¶
Only applies to the Self-Hosted Tempo via Grafana Proxy setup. If HolmesGPT reaches Grafana through an internal URL but you want the clickable "View in Grafana" links in responses to use a public URL:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: http://grafana.monitoring.svc.cluster.local # Internal URL for API calls
api_key: <your grafana API key>
grafana_datasource_uid: <tempo datasource uid>
external_url: https://grafana.example.com # URL used in clickable links
Custom Label Mappings¶
Tempo uses resource attributes to identify Kubernetes resources. If your setup uses non-default attribute names, you can customize the mappings:
toolsets:
grafana/tempo:
enabled: true
config:
api_url: https://grafana.example.com
api_key: <your grafana API key>
grafana_datasource_uid: <tempo datasource uid>
labels:
pod: "k8s.pod.name" # default
namespace: "k8s.namespace.name" # default
deployment: "k8s.deployment.name" # default
node: "k8s.node.name" # default
service: "service.name" # default
Example Usage¶
Finding Slow Traces¶
Holmes will use TraceQL to search for slow operations:
Analyzing Errors¶
Holmes will search using:
Capabilities¶
| Tool Name | Description |
|---|---|
| tempo_fetch_traces_comparative_sample | Fetches statistics and samples of fast/slow/typical traces for performance analysis |
| tempo_search_traces_by_query | Search traces using TraceQL query language (recommended) |
| tempo_search_traces_by_tags | Search traces using logfmt-encoded tags (legacy) |
| tempo_query_trace_by_id | Retrieve detailed trace information by trace ID |
| tempo_search_tag_names | Discover available tag names across traces |
| tempo_search_tag_values | Get all values for a specific tag |
| tempo_query_metrics_instant | Compute a single TraceQL metric value across time range |
| tempo_query_metrics_range | Get time series data from TraceQL metrics queries |