You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I like the idea! Assuming one would like to check one tenant, the user should probably set the tenant-id in the configs to identify metrics for this tenant. The only tricky part could be to map tenants to dashboards, as one Grafana might be used for multiple tenants, have you got an idea for that?
The only thing I can think of quickly is parsing the dashboard for datasource uids, which will break in case of templated datasources.
I think there are some limitations to this tool, that need to be elicited. Do you think one should be able to query both Prometheus and Mimir or just one of both? The first one is likely an edge case, and I'm not sure if it's worth including over the additional complexity?
I'd like to pick this up. On whether to query both Prometheus and Mimir: I'd keep one backend per run. Mimir serves the endpoints cardamon calls (/api/v1/label/__name__/values, /api/v1/series, /api/v1/query and /api/v1/rules) under /prometheus by default, and path_prefix already handles that. The rules endpoint is served by Mimir's ruler, so that covers the ruler part too. On the API side, the main gap is the tenant header. Comparing Prometheus and Mimir would then be two runs with two configs.
I'd split it into two parts:
prometheus.tenant_id, sent as X-Scope-OrgID on every Prometheus request, as you suggested. If it's empty, no header is sent, so nothing changes for plain Prometheus. One run audits one tenant, so a per-tenant report is one config per tenant. This part is small, and I'll open a PR for it right after this comment.
Matching dashboards to tenants. Grafana stores the value of a datasource's custom header in secureJsonData, and /api/datasources only shows that the field is set, so I don't think cardamon can work out a datasource's tenant by itself. Instead, I'd add an optional grafana.datasource_uids list. Cardamon would parse each dashboard's JSON and count a metric as used only if a query on one of those datasources uses it. If it can't pin a query to a single datasource (for example a templated $ds), or can't parse a dashboard, it counts those metrics as used. A parsing gap can then leave an unused metric unflagged, but it can't flag a used one. This also fixes the multiple-datasources case in the README's Limitations. Without the list, matching works as it does today.
Does that shape work for part 2, or would you rather list the dashboards in the config, as suggested above? I'll wait for your answer before writing it.
Activity
dominikhei commentedon Apr 9, 2026
I like the idea! Assuming one would like to check one tenant, the user should probably set the tenant-id in the configs to identify metrics for this tenant. The only tricky part could be to map tenants to dashboards, as one Grafana might be used for multiple tenants, have you got an idea for that?
The only thing I can think of quickly is parsing the dashboard for datasource uids, which will break in case of templated datasources.
ebarped commentedon Apr 9, 2026
dont we have the same issue right now with prometheus? if the dashboard also have multiple datasources of type prometheus, i mean 🤔
dominikhei commentedon Apr 9, 2026
Yes, but so far it assumes a single Prometheus instance.
ebarped commentedon Apr 9, 2026
We could also set the dashboards to check in the config, assuming that all of those panels use the datasources from your config.
The problem is that it would feel a little bit "rigid", and some metrics will result in false positives... 😢
dominikhei commentedon Apr 12, 2026
I think there are some limitations to this tool, that need to be elicited. Do you think one should be able to query both Prometheus and Mimir or just one of both? The first one is likely an edge case, and I'm not sure if it's worth including over the additional complexity?
abd-ulbasit commentedon Oct 17, 2026
I'd like to pick this up. On whether to query both Prometheus and Mimir: I'd keep one backend per run. Mimir serves the endpoints cardamon calls (
/api/v1/label/__name__/values,/api/v1/series,/api/v1/queryand/api/v1/rules) under/prometheusby default, andpath_prefixalready handles that. The rules endpoint is served by Mimir's ruler, so that covers the ruler part too. On the API side, the main gap is the tenant header. Comparing Prometheus and Mimir would then be two runs with two configs.I'd split it into two parts:
prometheus.tenant_id, sent asX-Scope-OrgIDon every Prometheus request, as you suggested. If it's empty, no header is sent, so nothing changes for plain Prometheus. One run audits one tenant, so a per-tenant report is one config per tenant. This part is small, and I'll open a PR for it right after this comment.secureJsonData, and/api/datasourcesonly shows that the field is set, so I don't think cardamon can work out a datasource's tenant by itself. Instead, I'd add an optionalgrafana.datasource_uidslist. Cardamon would parse each dashboard's JSON and count a metric as used only if a query on one of those datasources uses it. If it can't pin a query to a single datasource (for example a templated$ds), or can't parse a dashboard, it counts those metrics as used. A parsing gap can then leave an unused metric unflagged, but it can't flag a used one. This also fixes the multiple-datasources case in the README's Limitations. Without the list, matching works as it does today.Does that shape work for part 2, or would you rather list the dashboards in the config, as suggested above? I'll wait for your answer before writing it.