Skip to content

Fix Loki toolset docs for Grafana Cloud and trailing slash bug - #1590

Open
aantn wants to merge 5 commits into
masterfrom
claude/fix-loki-docs-tSHIk
Open

aantn wants to merge 5 commits into
masterfrom
claude/fix-loki-docs-tSHIk

Conversation

@aantn

@aantn aantn commented Feb 19, 2026 •

Copy link
Copy Markdown
Collaborator

Add dedicated Grafana Cloud section to Loki docs with step-by-step
instructions for service account setup, datasource UID discovery, and
common mistake warnings. Fix trailing slash bug in get_base_url() that
produced double-slash URLs (e.g. https://x.grafana.net//api/...) causing
404 errors. Also add direct Grafana Cloud Loki access method and correct
the capabilities table tool name.

https://claude.ai/code/session_01CcT3RF7eByFp1W1mtdbXyK
Signed-off-by: Claude noreply@anthropic.com

Summary by CodeRabbit

  • Documentation

    • Expanded Grafana Loki guide with separate Self‑Hosted Grafana, Grafana Cloud, and direct‑to‑Loki setups, plus new option blocks and labeled contexts.
    • Added curl/examples for connection modes, GLSA/Grafana token creation steps, 404 troubleshooting, SSL/external URL guidance, and reorganized headers for clarity.
  • Bug Fixes

    • Fixed API URL formatting to remove duplicate slashes.
    • Renamed public capability from fetch_pod_logs to grafana_loki_query.

Add dedicated Grafana Cloud section to Loki docs with step-by-step
instructions for service account setup, datasource UID discovery, and
common mistake warnings. Fix trailing slash bug in get_base_url() that
produced double-slash URLs (e.g. https://x.grafana.net//api/...) causing
404 errors. Also add direct Grafana Cloud Loki access method and correct
the capabilities table tool name.

https://claude.ai/code/session_01CcT3RF7eByFp1W1mtdbXyK
Signed-off-by: Claude <noreply@anthropic.com>
@netlify

netlify Bot commented Feb 19, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for holmes-docs ready!

Name Link
🔨 Latest commit 96716a7
🔍 Latest deploy log https://app.netlify.com/projects/holmes-docs/deploys/69976665a37ca00009cc8cf0
😎 Deploy Preview https://deploy-preview-1590--holmes-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Feb 19, 2026 •

Copy link
Copy Markdown
Contributor

✅ Docker image ready for 4b90f0b (built in 42s)

⚠️ Warning: does not support ARM (ARM images are built on release only - not on every PR)

Use this tag to pull the image for testing.

📋 Copy commands

⚠️ Temporary images are deleted after 30 days. Copy to a permanent registry before using them:

gcloud auth configure-docker us-central1-docker.pkg.dev
docker pull us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:4b90f0b
docker tag us-central1-docker.pkg.dev/robusta-development/temporary-builds/holmes:4b90f0b me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:4b90f0b
docker push me-west1-docker.pkg.dev/robusta-development/development/holmes-dev:4b90f0b

Patch Helm values in one line (choose the chart you use):

HolmesGPT chart:

helm upgrade --install holmesgpt ./helm/holmes \
  --set registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set image=holmes-dev:4b90f0b

Robusta wrapper chart:

helm upgrade --install robusta robusta/robusta \
  --reuse-values \
  --set holmes.registry=me-west1-docker.pkg.dev/robusta-development/development \
  --set holmes.image=holmes-dev:4b90f0b

@github-actions

github-actions Bot commented Feb 19, 2026 •

Copy link
Copy Markdown
Contributor

📂 Previous Runs

📜 Run @ 17fa0ee (#22177689261)

✅ Results of HolmesGPT evals

Automatically triggered by commit 17fa0ee on branch claude/fix-loki-docs-tSHIk

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 34.9s 5 11 $0.2402
✅ 101_loki_historical_logs_pod_deleted 33.6s 4 8 $0.2157
✅ 111_pod_names_contain_service 36.5s 5 12 $0.2385
✅ 112_find_pvcs_by_uuid 40.3s 7 9 $0.2670
✅ 12_job_crashing 34.4s 5 11 $0.2468
✅ 176_network_policy_blocking_traffic_no_runbooks 43.9s 6 17 $0.2984
✅ 24_misconfigured_pvc 38.2s 6 14 $0.2491
✅ 43_current_datetime_from_prompt 6.2s 1 — $0.1119
✅ 61_exact_match_counting 15.4s 3 2 $0.1487
Total 31.5s avg 4.7 avg 10.5 avg $2.0162
📜 Run @ 7ddeeab (#22176994733)

✅ Results of HolmesGPT evals

Automatically triggered by commit 7ddeeab on branch claude/fix-loki-docs-tSHIk

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 33.7s 5 12 $0.2485
✅ 101_loki_historical_logs_pod_deleted 49.7s 7 11 $0.2901
✅ 111_pod_names_contain_service 34.6s 5 11 $0.2318
✅ 112_find_pvcs_by_uuid 25.5s 4 5 $0.2020
✅ 12_job_crashing 46.2s 7 18 $0.3183
✅ 176_network_policy_blocking_traffic_no_runbooks 48.9s 7 17 $0.2946
✅ 24_misconfigured_pvc 37.4s 6 15 $0.2525
✅ 43_current_datetime_from_prompt 5.6s 1 — $0.1120
✅ 61_exact_match_counting 16.9s 4 4 $0.1678
Total 33.2s avg 5.1 avg 11.6 avg $2.1176
📜 Run @ 7ce3762 (#22176822295)

✅ Results of HolmesGPT evals

Automatically triggered by commit 7ce3762 on branch claude/fix-loki-docs-tSHIk

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 37.8s 5 12 $0.2524
✅ 101_loki_historical_logs_pod_deleted 53.3s 6 12 $0.3033
✅ 111_pod_names_contain_service 39.5s 5 11 $0.2372
✅ 112_find_pvcs_by_uuid 35.9s 6 9 $0.2491
✅ 12_job_crashing 37.8s 5 12 $0.2572
✅ 176_network_policy_blocking_traffic_no_runbooks 43.8s 6 15 $0.2831
✅ 24_misconfigured_pvc 34.3s 5 13 $0.2379
✅ 43_current_datetime_from_prompt 5.2s 1 — $0.1112
✅ 61_exact_match_counting 15.5s 3 2 $0.1526
Total 33.7s avg 4.7 avg 10.8 avg $2.0840

✅ Results of HolmesGPT evals

Automatically triggered by commit 96716a7 on branch claude/fix-loki-docs-tSHIk

View workflow logs

Results of HolmesGPT evals

  • ask_holmes: 9/9 test cases were successful, 0 regressions
Status Test case Time Turns Tools Cost
✅ 09_crashpod 33.1s 5 11 $0.2414
✅ 101_loki_historical_logs_pod_deleted 49.4s 6 13 $0.2962
✅ 111_pod_names_contain_service 33.4s 5 12 $0.2394
✅ 112_find_pvcs_by_uuid 32.7s 6 7 $0.2394
✅ 12_job_crashing 25.6s 4 7 $0.2019
✅ 176_network_policy_blocking_traffic_no_runbooks 47.4s 7 16 $0.3067
✅ 24_misconfigured_pvc 36.5s 6 14 $0.2564
✅ 43_current_datetime_from_prompt 5.0s 1 — $0.1114
✅ 61_exact_match_counting 12.3s 3 2 $0.1491
Total 30.6s avg 4.8 avg 10.2 avg $2.0419
📖 Legend
Icon Meaning
✅ The test was successful
➖ The test was skipped
⚠️ The test failed but is known to be flaky or known to fail
🚧 The test had a setup failure (not a code regression)
🔧 The test failed due to mock data issues (not a code regression)
🚫 The test was throttled by API rate limits/overload
❌ The test failed and should be fixed before merging the PR
🔄 Re-run evals manually

⚠️ Warning: /eval comments always run using the workflow from master, not from this PR branch. If you modified the GitHub Action (e.g., added secrets or env vars), those changes won't take effect.

To test workflow changes, use the GitHub CLI or Actions UI instead:

gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/fix-loki-docs-tSHIk -f markers=regression -f filter=

Option 1: Comment on this PR with /eval:

/eval
markers: regression

Or with more options (one per line):

/eval
model: gpt-4o
markers: regression
filter: 09_crashpod
iterations: 5

Run evals on a different branch (e.g., master) for comparison:

/eval
branch: master
markers: regression
Option Description
model Model(s) to test (default: same as automatic runs)
markers Pytest markers (no default - runs all tests!)
filter Pytest -k filter (use /list to see valid eval names)
iterations Number of runs, max 10
branch Run evals on a different branch (for cross-branch comparison)

Quick re-run: Use /rerun to re-run the most recent /eval on this PR with the same parameters.

Option 2: Trigger via GitHub Actions UI → "Run workflow"

🏷️ Valid markers

benchmark, chain-of-causation, compaction, confluence, context_window, coralogix, counting, database, datadog, datetime, easy, elasticsearch, embeds, fast, frontend, grafana-dashboard, hard, integration, kafka, kubernetes, leaked-information, logs, loki, medium, metrics, network, newrelic, no-cicd, numerical, one-test, port-forward, prometheus, question-answer, regression, runbooks, slackbot, storage, toolset-limitation, traces, transparency


Commands: /eval · /rerun · /list

CLI: gh workflow run eval-regression.yaml --repo HolmesGPT/holmesgpt --ref claude/fix-loki-docs-tSHIk -f markers=regression -f filter=

@coderabbitai

coderabbitai Bot commented Feb 19, 2026 •

Copy link
Copy Markdown
Contributor

Walkthrough

Docs reorganized to present Grafana proxy, Grafana Cloud, Self‑Hosted, and direct‑to‑Loki connection flows; code stabilizes Grafana API URL by stripping trailing slashes in get_base_url; a test expectation updated to match the corrected URL formatting.

Changes

Cohort / File(s) Summary
Documentation
docs/data-sources/builtin-toolsets/grafanaloki.md
Rewrote configuration layout into explicit contexts (Grafana Cloud, Self‑Hosted, Direct Loki), added GLSA/service-account token steps, 404 troubleshooting, SSL/external URL notes, curl examples, and renamed public capability from fetch_pod_logs to grafana_loki_query.
Grafana URL handling
holmes/plugins/toolsets/grafana/common.py
Normalize config.api_url by rstrip-ing trailing slashes into a local api_url and use it in both branches of get_base_url to prevent double-slash in constructed URLs.
Tests
tests/plugins/toolsets/grafana/test_grafana.py
Updated test expected error URL to remove an extra slash (changed //api/... to /api/...).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • Sheeproid
  • Avi-Robusta
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the two primary changes: documentation improvements for Grafana Cloud's Loki toolset and a trailing slash bug fix in the URL handling code.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Feb 19, 2026 •

Copy link
Copy Markdown
Contributor

🔬 CLI Performance Benchmark

🟡 Startup Time (no LLM)

Measures holmes version execution time (imports + initialization)

Metric PR Master Change
Cold Start 11.02s 10.41s +5.9%
Warm Mean 4.72s 4.55s +3.6%
Warm Min 4.67s 4.52s
Warm Max 4.76s 4.60s

🟡 Full CLI with LLM

Measures holmes ask execution time (OpenRouter + Haiku 4.5)

Metric PR Master Change
Cold Start 36.03s 40.06s -10.0%
Warm Mean 7.84s 7.54s +4.0%
Warm Min 7.18s 6.91s
Warm Max 8.49s 8.12s

PR: 4b90f0b0 | Master: abb2c746 | Iterations: 5

The old Options 1/2/3 were confusing because "Grafana Cloud" is just
Grafana. Restructured into two real options:
- Option 1: Through Grafana (self-hosted or cloud, via tabs)
- Option 2: Direct to Loki (self-hosted or cloud, via tabs)

https://claude.ai/code/session_01CcT3RF7eByFp1W1mtdbXyK
Signed-off-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
docs/data-sources/builtin-toolsets/grafanaloki.md (1)

105-118: Consider adding a base64 generation command for clarity.

Authorization: "Basic <base64 of USER_ID:API_KEY>" leaves the credential type of API_KEY ambiguous (Grafana Cloud API token vs account password) and doesn't show how to produce the encoded value. Consistent with the rest of the doc's hands-on approach, a one-liner would help:

✏️ Suggested addition after the YAML block
+To generate the Base64 value (use your numeric user ID and a Grafana Cloud API token):
+```bash
+echo -n "YOUR_USER_ID:YOUR_API_KEY" | base64
+```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/data-sources/builtin-toolsets/grafanaloki.md` around lines 105 - 118,
The docs snippet for Grafana Cloud Loki direct access leaves the Authorization
header unclear and lacks a command to generate the base64 string; update the
description after the YAML example that contains the Authorization: "Basic
<base64 of USER_ID:API_KEY>" line to explicitly state that API_KEY refers to the
Grafana Cloud API key/token (not account password) and add a one-line example
showing how to produce the base64 value (echo -n "USER_ID:API_KEY" | base64) so
users know how to generate the encoded credential for the Authorization header.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/data-sources/builtin-toolsets/grafanaloki.md`:
- Around line 105-118: The docs snippet for Grafana Cloud Loki direct access
leaves the Authorization header unclear and lacks a command to generate the
base64 string; update the description after the YAML example that contains the
Authorization: "Basic <base64 of USER_ID:API_KEY>" line to explicitly state that
API_KEY refers to the Grafana Cloud API key/token (not account password) and add
a one-line example showing how to produce the base64 value (echo -n
"USER_ID:API_KEY" | base64) so users know how to generate the encoded credential
for the Authorization header.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/data-sources/builtin-toolsets/grafanaloki.md (1)

151-155: Capabilities section violates the documentation guideline.

The table lists the tool name and a description of what it does. As per coding guidelines: "In 'Capabilities' sections, don't list what a toolset/integration can do — users discover capabilities by using Holmes. Feature lists become stale quickly."

Consider removing the ## Capabilities section entirely.

✏️ Suggested removal
-## Capabilities
-
-| Tool Name | Description |
-|-----------|-------------|
-| grafana_loki_query | Run LogQL queries against Loki |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/data-sources/builtin-toolsets/grafanaloki.md` around lines 151 - 155,
Remove the entire "## Capabilities" section (including the table and the
"grafana_loki_query" row) from docs/data-sources/builtin-toolsets/grafanaloki.md
so the documentation no longer enumerates feature capabilities; ensure no
leftover header or table markup remains (delete the "## Capabilities" heading
and the pipe-table block that lists grafana_loki_query).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/data-sources/builtin-toolsets/grafanaloki.md`:
- Around line 43-49: The documentation shows the curl command that requires
YOUR_GLSA_TOKEN before the instructions that explain how to obtain that token,
which can confuse readers; move the sentence starting "To create a service
account token: navigate to \"Administration → Service accounts\", create a new
service account with \"Viewer\" role, and generate a token (starts with
`glsa_`)." so it appears immediately before the curl block (i.e., place the
service account creation instructions above the curl command that calls "curl -H
\"Authorization: Bearer YOUR_GLSA_TOKEN\" ..."), preserving wording and
formatting (bolding if present) and keeping the curl code block unchanged.

---

Nitpick comments:
In `@docs/data-sources/builtin-toolsets/grafanaloki.md`:
- Around line 151-155: Remove the entire "## Capabilities" section (including
the table and the "grafana_loki_query" row) from
docs/data-sources/builtin-toolsets/grafanaloki.md so the documentation no longer
enumerates feature capabilities; ensure no leftover header or table markup
remains (delete the "## Capabilities" heading and the pipe-table block that
lists grafana_loki_query).

Comment on lines +43 to +49
```bash
curl -H "Authorization: Bearer YOUR_GLSA_TOKEN" \
"https://YOUR-INSTANCE.grafana.net/api/datasources" | \
jq '.[] | select(.type=="loki") | {name, uid}'
```

The toolset can directly connect to a Loki instance without proxying through a Grafana instance. This is done by not setting the `grafana_datasource_uid` field. Not setting this field makes HolmesGPT assume that it is directly connecting to Loki.
To create a service account token: navigate to "Administration → Service accounts", create a new service account with "Viewer" role, and generate a token (starts with `glsa_`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Token creation instructions appear after the curl that requires the token.

A reader following the steps sequentially would encounter the curl -H "Authorization: Bearer YOUR_GLSA_TOKEN" command before being told how to obtain YOUR_GLSA_TOKEN. Swapping the order — service account creation instructions first, curl command second — removes this catch-22.

✏️ Suggested reorder
 === "Grafana Cloud"

-    ```bash
-    curl -H "Authorization: Bearer YOUR_GLSA_TOKEN" \
-         "https://YOUR-INSTANCE.grafana.net/api/datasources" | \
-         jq '.[] | select(.type=="loki") | {name, uid}'
-    ```
-
-    To create a service account token: navigate to "Administration → Service accounts", create a new service account with "Viewer" role, and generate a token (starts with `glsa_`).
+    To create a service account token: navigate to **Administration → Service accounts**, create a new service account with **Viewer** role, and generate a token (starts with `glsa_`).
+
+    ```bash
+    curl -H "Authorization: Bearer YOUR_GLSA_TOKEN" \
+         "https://YOUR-INSTANCE.grafana.net/api/datasources" | \
+         jq '.[] | select(.type=="loki") | {name, uid}'
+    ```

Note on static analysis: Both Gitleaks findings for this block are false positives — admin:admin is the standard local Grafana default against localhost:3000, and YOUR_GLSA_TOKEN is a documentation placeholder, not a real credential.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```bash
curl -H "Authorization: Bearer YOUR_GLSA_TOKEN" \
"https://YOUR-INSTANCE.grafana.net/api/datasources" | \
jq '.[] | select(.type=="loki") | {name, uid}'
```
The toolset can directly connect to a Loki instance without proxying through a Grafana instance. This is done by not setting the `grafana_datasource_uid` field. Not setting this field makes HolmesGPT assume that it is directly connecting to Loki.
To create a service account token: navigate to "Administration → Service accounts", create a new service account with "Viewer" role, and generate a token (starts with `glsa_`).
To create a service account token: navigate to **Administration → Service accounts**, create a new service account with **Viewer** role, and generate a token (starts with `glsa_`).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/data-sources/builtin-toolsets/grafanaloki.md` around lines 43 - 49, The
documentation shows the curl command that requires YOUR_GLSA_TOKEN before the
instructions that explain how to obtain that token, which can confuse readers;
move the sentence starting "To create a service account token: navigate to
\"Administration → Service accounts\", create a new service account with
\"Viewer\" role, and generate a token (starts with `glsa_`)." so it appears
immediately before the curl block (i.e., place the service account creation
instructions above the curl command that calls "curl -H \"Authorization: Bearer
YOUR_GLSA_TOKEN\" ..."), preserving wording and formatting (bolding if present)
and keeping the curl code block unchanged.

The code automatically adds Bearer auth from api_key, so no need for
manual additional_headers with Basic auth.

https://claude.ai/code/session_01CcT3RF7eByFp1W1mtdbXyK
Signed-off-by: Claude <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/data-sources/builtin-toolsets/grafanaloki.md`:
- Around line 106-120: Update the Grafana Cloud Loki docs for the grafana/loki
toolset to require and document the tenant ID and Access Policy token (with
logs:read scope) instead of only api_key: explain that Grafana Cloud requires
either HTTP Basic Auth (username=tenant_id, password=access_policy_token) or an
Authorization: Bearer header in the form TENANT_ID:TOKEN, and add a new config
field suggestion tenant_id (or show using additional_headers with Authorization:
Basic <base64 tenant:token>) alongside api_key/access_policy_token; clarify that
glsa_* service account tokens are not acceptable and update the example config
under toolsets.grafana/loki to demonstrate the correct fields and authentication
method for direct Loki endpoints.

---

Duplicate comments:
In `@docs/data-sources/builtin-toolsets/grafanaloki.md`:
- Around line 43-49: Move the service account token creation sentence so it
appears before the curl command that references YOUR_GLSA_TOKEN; specifically,
place the sentence "To create a service account token: navigate to
'Administration → Service accounts', create a new service account with 'Viewer'
role, and generate a token (starts with `glsa_`)." immediately above the ```bash
curl -H "Authorization: Bearer YOUR_GLSA_TOKEN" ...``` block so readers know how
to obtain the token before the curl example uses it.

Comment on lines +106 to +120
=== "Grafana Cloud Loki"

Find your Loki URL in Grafana Cloud under "My Account → Loki":

```yaml-toolset-config
toolsets:
grafana/loki:
enabled: true
config:
api_url: https://logs-prod-XXX.grafana.net
api_key: <your Grafana Cloud API key>

kubernetes/logs:
enabled: false # HolmesGPT's default logging mechanism MUST be disabled
```

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "common.py" -path "*/grafana/*" | head -20

Repository: HolmesGPT/holmesgpt

Length of output: 106


🏁 Script executed:

rg -n "api_key|Bearer|basic_auth|Authorization" --type py -A3 -B3 holmes/plugins/toolsets/grafana/common.py

Repository: HolmesGPT/holmesgpt

Length of output: 1044


🏁 Script executed:

find . -name "*.py" -path "*/loki*" -o -name "*loki*" -type f | head -20

Repository: HolmesGPT/holmesgpt

Length of output: 392


🏁 Script executed:

rg -i "grafana.*loki|loki.*cloud|basic.*auth|instance.*id" --type py -A2 -B2 | head -100

Repository: HolmesGPT/holmesgpt

Length of output: 6629


🏁 Script executed:

cat -n holmes/plugins/toolsets/grafana/loki_api.py

Repository: HolmesGPT/holmesgpt

Length of output: 3362


🌐 Web query:

Grafana Cloud Loki authentication API key bearer token

💡 Result:

For Grafana Cloud Loki (logs), the “API key” you create is typically a Grafana Cloud Access Policy token. How you pass it depends on which endpoint you’re calling:

1) Calling Loki (read/write logs): use tenant/user + token

Grafana Cloud Loki expects your Logs tenant ID (a.k.a. logs user / tenant) plus the token.

Option A — HTTP Basic Auth (most common)

  • Username: your logs tenant ID
  • Password: your Access Policy token (Grafana Cloud token) (grafana.com)

Option B — Authorization: Bearer <user>:<token> (common for push examples)

Grafana’s own curl example for pushing logs uses:
Authorization: Bearer <LOGS_USERID>:<API_KEY> (grafana.com)

Example (push):

curl -X POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <LOGS_TENANT_ID>:<ACCESS_POLICY_TOKEN>" \
  -d '{"streams":[{"stream":{"source":"curl"},"values":[["'"$(($(date +%s)*1000000000))"'","hello"]]}]}' \
  https://<your-loki-endpoint>/loki/api/v1/push

(grafana.com)

2) Calling the Grafana Cloud API (not Loki): use Bearer <token>

For Grafana Cloud API requests, you pass the Access Policy token as:
Authorization: Bearer <CLOUD ACCESS POLICY TOKEN> (grafana.com)

If you tell me whether you’re pushing logs (/loki/api/v1/push) or querying (/loki/api/v1/query / query_range), and paste your Loki endpoint host pattern (redact IDs), I can give you the exact curl for your case.

Citations:


🌐 Web query:

Grafana Cloud Loki query_range authentication tenant ID logs user

💡 Result:

To call Loki’s GET /loki/api/v1/query_range against Grafana Cloud Logs (Loki) you typically need (a) the logs tenant ID / logs userID and (b) a token (Cloud Access Policy token) with logs:read.

1) Endpoint

Use your stack’s Loki “Logs endpoint” (shown in the Grafana Cloud Portal). The range-query path is: .../loki/api/v1/query_range. [1]

2) Authentication (Grafana Cloud)

Grafana Cloud’s recommended setup is HTTP Basic Auth:

  • Username = log tenant ID (often shown as “Logs user” / “UserID” in the Cloud Portal)
  • Password = Grafana Cloud token (Cloud Access Policy token) [2]

3) Tenant / Org header (X-Scope-OrgID)

Loki is multi-tenant and, in general, identifies the tenant with the X-Scope-OrgID header. [3]
In Grafana Cloud, the fronting gateway commonly derives tenant from your credentials (so you often don’t need to manually add X-Scope-OrgID if you’re using the Cloud endpoint + basic auth), but if you’re hitting Loki behind your own proxy or a custom deployment, you may need to set it explicitly. [3]

4) Example curl (range query)

curl -u "$LOKI_TENANT_ID:$GRAFANA_CLOUD_TOKEN" \
  "https://<your-logs-endpoint>/loki/api/v1/query_range?query=%7Bjob%3D%22api%22%7D&start=1700000000000000000&end=1700003600000000000&limit=1000"

Common failure modes

  • Using a token without logs:read scope. [2]
  • Using the wrong “user/tenant ID” (must be the logs tenant ID, not your email/login). [2]
  • Missing/incorrect X-Scope-OrgID when talking to Loki without a gateway that injects it. [3]

Sources: [1] [2] [3]


🏁 Script executed:

cat -n holmes/plugins/toolsets/grafana/common.py | head -60

Repository: HolmesGPT/holmesgpt

Length of output: 2498


🏁 Script executed:

cat -n holmes/plugins/toolsets/grafana/loki/toolset_grafana_loki.py | head -100

Repository: HolmesGPT/holmesgpt

Length of output: 4074


The Grafana Cloud Loki configuration example is incomplete for direct-access authentication.

Grafana Cloud Loki requires both the logs tenant ID (numeric user ID) and an Access Policy token with logs:read scope. Official Grafana documentation specifies HTTP Basic Auth (username=tenant ID, password=token) or Authorization: Bearer <TENANT_ID>:<TOKEN>.

The current code implements only Authorization: Bearer <api_key>, omitting the tenant ID. This will fail for Grafana Cloud Loki direct access (logs-prod-XXX.grafana.net/loki/api/v1/...).

The configuration should:

  1. Clarify that a Grafana Cloud Access Policy token (not a service account token like glsa_*) is required with logs:read scope.
  2. Document that the logs tenant/user ID must be provided—either via a new tenant_id config field or through additional_headers using HTTP Basic Auth (Authorization: Basic <base64-encoded-tenant:token>).
  3. Update the example to show how users can configure direct Loki access with proper authentication.

Without this, users following the current example with a direct Loki endpoint will encounter authentication errors.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/data-sources/builtin-toolsets/grafanaloki.md` around lines 106 - 120,
Update the Grafana Cloud Loki docs for the grafana/loki toolset to require and
document the tenant ID and Access Policy token (with logs:read scope) instead of
only api_key: explain that Grafana Cloud requires either HTTP Basic Auth
(username=tenant_id, password=access_policy_token) or an Authorization: Bearer
header in the form TENANT_ID:TOKEN, and add a new config field suggestion
tenant_id (or show using additional_headers with Authorization: Basic <base64
tenant:token>) alongside api_key/access_policy_token; clarify that glsa_*
service account tokens are not acceptable and update the example config under
toolsets.grafana/loki to demonstrate the correct fields and authentication
method for direct Loki endpoints.

- Move Grafana Cloud service account creation instructions before
  the curl command that references the token
- Remove Capabilities table per docs guidelines

https://claude.ai/code/session_01CcT3RF7eByFp1W1mtdbXyK
Signed-off-by: Claude <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants