-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Datasources Not in Use #70
Comments
Dear @meyerder, thank you for your suggestions, and apologies for the late reply. I will try to consider them on the next development iteration. If you think you could submit one or another patch to improve the situation on a few of the details you are referring to, it will be much appreciated! With kind regards, |
Hi again, did you have a chance to verify if the corresponding improvement works well for you? With kind regards, |
I did not test... I actually accomplished what I was looking for by doing this via the Database {
"__inputs": [
{
"name": "DS_MYSQL",
"label": "MySQL",
"description": "",
"type": "datasource",
"pluginId": "mysql",
"pluginName": "MySQL"
}
],
"__elements": {},
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "9.5.7"
},
{
"type": "datasource",
"id": "mysql",
"name": "MySQL",
"version": "1.0.0"
},
{
"type": "panel",
"id": "table",
"name": "Table",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": {
"type": "grafana",
"uid": "-- Grafana --"
},
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"description": "All Dashboard Panel Querys to Datasources",
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "mysql",
"uid": "${DS_MYSQL}"
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"custom": {
"align": "auto",
"cellOptions": {
"type": "auto"
},
"filterable": true,
"inspect": false
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 30,
"w": 24,
"x": 0,
"y": 0
},
"id": 1,
"options": {
"cellHeight": "sm",
"footer": {
"countRows": false,
"fields": "",
"reducer": [
"sum"
],
"show": false
},
"showHeader": true,
"sortBy": []
},
"pluginVersion": "9.5.7",
"targets": [
{
"datasource": {
"type": "mysql",
"uid": "${DS_MYSQL}"
},
"editorMode": "code",
"format": "table",
"rawQuery": true,
"rawSql": "SELECT\r\n d.slug,\r\n d.title,\r\n panel_datasource.datasource_type,\r\n panel_datasource.datasource_uid,\r\n COALESCE(target_data_raw.query, target_data_expr.query, target_data_jql.query, target_data.query) AS QUERY\r\nFROM\r\n (\r\n SELECT\r\n dashboard_id,\r\n JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.datasource.type')) AS datasource_type,\r\n JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.datasource.uid')) AS datasource_uid,\r\n panel_index\r\n FROM\r\n (\r\n SELECT\r\n d.id AS dashboard_id,\r\n panel_data,\r\n ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index\r\n FROM\r\n dashboard AS d,\r\n JSON_TABLE(\r\n d.data,\r\n \"$.panels[*]\" COLUMNS (\r\n panel_data JSON PATH \"$\",\r\n panel_index FOR ORDINALITY\r\n )\r\n ) AS jt\r\n WHERE\r\n d.org_id in ($ORG)\r\n ) AS panel_data_with_index\r\n ) AS panel_datasource\r\nLEFT JOIN\r\n (\r\n SELECT\r\n dashboard_id,\r\n JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.rawSql')) AS QUERY,\r\n panel_index\r\n FROM\r\n (\r\n SELECT\r\n d.id AS dashboard_id,\r\n panel_data,\r\n ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index\r\n FROM\r\n dashboard AS d,\r\n JSON_TABLE(\r\n d.data,\r\n \"$.panels[*].targets[*]\" COLUMNS (\r\n panel_data JSON PATH \"$\",\r\n panel_index FOR ORDINALITY\r\n )\r\n ) AS jt\r\n WHERE\r\n d.org_id in ($ORG)\r\n ) AS target_data_with_index\r\n ) AS target_data_raw ON panel_datasource.dashboard_id = target_data_raw.dashboard_id AND panel_datasource.panel_index = target_data_raw.panel_index\r\nLEFT JOIN\r\n (\r\n SELECT\r\n dashboard_id,\r\n JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.expr')) AS QUERY,\r\n panel_index\r\n FROM\r\n (\r\n SELECT\r\n d.id AS dashboard_id,\r\n panel_data,\r\n ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index\r\n FROM\r\n dashboard AS d,\r\n JSON_TABLE(\r\n d.data,\r\n \"$.panels[*].targets[*]\" COLUMNS (\r\n panel_data JSON PATH \"$\",\r\n panel_index FOR ORDINALITY\r\n )\r\n ) AS jt\r\n WHERE\r\n d.org_id in ($ORG)\r\n ) AS target_data_with_index\r\n ) AS target_data_expr ON panel_datasource.dashboard_id = target_data_expr.dashboard_id AND panel_datasource.panel_index = target_data_expr.panel_index\r\nLEFT JOIN\r\n (\r\n SELECT\r\n dashboard_id,\r\n JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.jql')) AS QUERY,\r\n panel_index\r\n FROM\r\n (\r\n SELECT\r\n d.id AS dashboard_id,\r\n panel_data,\r\n ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index\r\n FROM\r\n dashboard AS d,\r\n JSON_TABLE(\r\n d.data,\r\n \"$.panels[*].targets[*]\" COLUMNS (\r\n panel_data JSON PATH \"$\",\r\n panel_index FOR ORDINALITY\r\n )\r\n ) AS jt\r\n WHERE\r\n d.org_id in ($ORG)\r\n ) AS target_data_with_index\r\n ) AS target_data_jql ON panel_datasource.dashboard_id = target_data_jql.dashboard_id AND panel_datasource.panel_index = target_data_jql.panel_index\r\nLEFT JOIN\r\n (\r\n SELECT\r\n dashboard_id,\r\n JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.query')) AS QUERY,\r\n panel_index\r\n FROM\r\n (\r\n SELECT\r\n d.id AS dashboard_id,\r\n panel_data,\r\n ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index\r\n FROM\r\n dashboard AS d,\r\n JSON_TABLE(\r\n d.data,\r\n \"$.panels[*].targets[*]\" COLUMNS (\r\n panel_data JSON PATH \"$\",\r\n panel_index FOR ORDINALITY\r\n )\r\n ) AS jt\r\n WHERE\r\n d.org_id in ($ORG)\r\n ) AS target_data_with_index\r\n ) AS target_data ON panel_datasource.dashboard_id = target_data.dashboard_id AND panel_datasource.panel_index = target_data.panel_index\r\nJOIN dashboard AS d ON panel_datasource.dashboard_id = d.id\r\nWHERE\r\n (target_data_raw.query IS NOT NULL AND target_data_raw.query <> '') OR\r\n (target_data_expr.query IS NOT NULL AND target_data_expr.query <> '') OR\r\n (target_data_jql.query IS NOT NULL AND target_data_jql.query <> '') OR\r\n (target_data.query IS NOT NULL AND target_data.query <> '');\r\n",
"refId": "A",
"sql": {
"columns": [
{
"parameters": [],
"type": "function"
}
],
"groupBy": [
{
"property": {
"type": "string"
},
"type": "groupBy"
}
],
"limit": 50
}
},
{
"datasource": {
"type": "mysql",
"uid": "${DS_MYSQL}"
},
"editorMode": "code",
"format": "table",
"hide": false,
"rawQuery": true,
"rawSql": "select name,uid as datasource_uid from data_source ",
"refId": "B",
"sql": {
"columns": [
{
"parameters": [],
"type": "function"
}
],
"groupBy": [
{
"property": {
"type": "string"
},
"type": "groupBy"
}
],
"limit": 50
}
}
],
"title": "Panel Title",
"transformations": [
{
"id": "merge",
"options": {}
}
],
"type": "table"
}
],
"refresh": "",
"schemaVersion": 38,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
"current": {},
"datasource": {
"type": "mysql",
"uid": "${DS_MYSQL}"
},
"definition": "select distinct org_id from dashboard",
"description": "Org ID number",
"hide": 0,
"includeAll": true,
"label": "Org ID number",
"multi": true,
"name": "ORG",
"options": [],
"query": "select distinct org_id from dashboard",
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 3,
"type": "query"
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "All Dashboard Panel Querys",
"uid": "d297b9f7-2cad-4f57-9772-64ce6866f7d2",
"version": 5,
"weekStart": ""
} |
The Key part of the above that is needed is this.. The only issue is that some of the older panels that may have been created in grafana 5,6,7,8 may not show properly as they migrated at one time from the datasource Name to a datasource_uid if the panels have not been migrated the UID and Datasource_Type are empty as well as the datasource Name.. That is part of what the above was attempting to figure out.. I leveraged what I found out by using your program to implement the below as trying to do it with JQ was just a PITA for me. SELECT
d.slug,
d.title,
panel_datasource.datasource_type,
panel_datasource.datasource_uid,
COALESCE(target_data_raw.query, target_data_expr.query, target_data_jql.query, target_data.query) AS QUERY
FROM
(
SELECT
dashboard_id,
JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.datasource.type')) AS datasource_type,
JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.datasource.uid')) AS datasource_uid,
panel_index
FROM
(
SELECT
d.id AS dashboard_id,
panel_data,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index
FROM
dashboard AS d,
JSON_TABLE(
d.data,
"$.panels[*]" COLUMNS (
panel_data JSON PATH "$",
panel_index FOR ORDINALITY
)
) AS jt
WHERE
d.org_id in ($ORG)
) AS panel_data_with_index
) AS panel_datasource
LEFT JOIN
(
SELECT
dashboard_id,
JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.rawSql')) AS QUERY,
panel_index
FROM
(
SELECT
d.id AS dashboard_id,
panel_data,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index
FROM
dashboard AS d,
JSON_TABLE(
d.data,
"$.panels[*].targets[*]" COLUMNS (
panel_data JSON PATH "$",
panel_index FOR ORDINALITY
)
) AS jt
WHERE
d.org_id in ($ORG)
) AS target_data_with_index
) AS target_data_raw ON panel_datasource.dashboard_id = target_data_raw.dashboard_id AND panel_datasource.panel_index = target_data_raw.panel_index
LEFT JOIN
(
SELECT
dashboard_id,
JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.expr')) AS QUERY,
panel_index
FROM
(
SELECT
d.id AS dashboard_id,
panel_data,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index
FROM
dashboard AS d,
JSON_TABLE(
d.data,
"$.panels[*].targets[*]" COLUMNS (
panel_data JSON PATH "$",
panel_index FOR ORDINALITY
)
) AS jt
WHERE
d.org_id in ($ORG)
) AS target_data_with_index
) AS target_data_expr ON panel_datasource.dashboard_id = target_data_expr.dashboard_id AND panel_datasource.panel_index = target_data_expr.panel_index
LEFT JOIN
(
SELECT
dashboard_id,
JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.jql')) AS QUERY,
panel_index
FROM
(
SELECT
d.id AS dashboard_id,
panel_data,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index
FROM
dashboard AS d,
JSON_TABLE(
d.data,
"$.panels[*].targets[*]" COLUMNS (
panel_data JSON PATH "$",
panel_index FOR ORDINALITY
)
) AS jt
WHERE
d.org_id in ($ORG)
) AS target_data_with_index
) AS target_data_jql ON panel_datasource.dashboard_id = target_data_jql.dashboard_id AND panel_datasource.panel_index = target_data_jql.panel_index
LEFT JOIN
(
SELECT
dashboard_id,
JSON_UNQUOTE(JSON_EXTRACT(panel_data, '$.query')) AS QUERY,
panel_index
FROM
(
SELECT
d.id AS dashboard_id,
panel_data,
ROW_NUMBER() OVER (PARTITION BY d.id ORDER BY jt.panel_index) AS panel_index
FROM
dashboard AS d,
JSON_TABLE(
d.data,
"$.panels[*].targets[*]" COLUMNS (
panel_data JSON PATH "$",
panel_index FOR ORDINALITY
)
) AS jt
WHERE
d.org_id in ($ORG)
) AS target_data_with_index
) AS target_data ON panel_datasource.dashboard_id = target_data.dashboard_id AND panel_datasource.panel_index = target_data.panel_index
JOIN dashboard AS d ON panel_datasource.dashboard_id = d.id
WHERE
(target_data_raw.query IS NOT NULL AND target_data_raw.query <> '') OR
(target_data_expr.query IS NOT NULL AND target_data_expr.query <> '') OR
(target_data_jql.query IS NOT NULL AND target_data_jql.query <> '') OR
(target_data.query IS NOT NULL AND target_data.query <> ''); |
Hi again, wow, thank you for sharing your solution, good that it works for you. As I recognize that you are storing your Grafana database within MySQL/MariaDB, you are leveraging the possibility to query it for the question you have, right? This is smart, but unfortunately it would be too specific to carry over to grafana-wtf. However, I would still like to improve it into the direction you are looking at, without needing you to resort to a jq statement. On this matter, I think I missed your second request within your original post:
I will look into it, thanks. With kind regards, |
Hi again, GH-89 may have a few improvements in this area, trying to generalize your use case and solution. Admittedly, I did not analyze your SQL statement too much 1, so there is plenty of room I got it wrong or missed important details. When this is the case, let me know if you think we can improve from there. With kind regards, Footnotes
|
Now, after fixing your posts to make the syntax highlighter work, I can see the main attributes you are interested in for the report you are looking at. SELECT
d.slug,
d.title,
panel_datasource.datasource_type,
panel_datasource.datasource_uid,
COALESCE(target_data_raw.query, target_data_expr.query, target_data_jql.query, target_data.query) AS QUERY To make the improved reporting mechanics of GH-89 behave like that, maybe without further ado, without needing any jq-based postprocessing in the future, will probably need another iteration. |
Hi again, we just released grafana-wtf 0.16.0, including the improvements from GH-89, see https://github.com/panodata/grafana-wtf/releases/tag/0.16.0. When combining the program with grafana-wtf explore dashboards --data-details --format=json | \
jq -r '.[].details | values[] | .[].query // "null"'
Please let us know if that works for you already, and whether it yields the correct results. If it works well, we may bring in corresponding filtering mechanisms into the code base itself. With kind regards, |
Hi again, after analyzing your SQL statement further, we discovered you are scanning all of With kind regards, Display information about data queries and their contexts within dashboardsgrafana-wtf explore dashboards --data-details --queries-only --format=json Do you think the output is reasonable? List queries used in all dashboardsAn extreme variant, filtering the output to display query expressions only. grafana-wtf explore dashboards --data-details --queries-only --format=json | \
jq '.[].details | values[] | .[] | .expr,.jql,.query,.rawSql | select( . != null and . != "" )' |
I might suggest this tweak to finding unused Data sources..
grafana-wtf/grafana-wtf-venv/lib/python3.7/site-packages/grafana_wtf/core.py
Reason:
Some older dashboards that are created are being triggered. The Name aspect has moved to uid and needs to account for both..
Request:
I have been trying to play with the jq syntax to extract the SQL statements of the data sources and not been able to do so yet. Do you have any suggestions?
Also a little note for those not familiar with python that much.. the version > .13 require pyton 3.7 or greater to run.
Thanks
The text was updated successfully, but these errors were encountered: