diff --git a/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/device_details.json b/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/device_details.json index f6d895f..ade5a39 100644 --- a/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/device_details.json +++ b/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/device_details.json @@ -250,13 +250,75 @@ "title": "Device Type Tag Over Time", "type": "state-timeline" }, + { + "datasource": { + "type": "influxdb", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 14, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": ["lastNotNull"], + "fields": "/.*/", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.2", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "${datasource}" + }, + "query": "// Get latest architecture and SoC per device\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n // Use CPU measurement to access the tags\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n // Group by device\n |> group(columns: [\"${unique_identifier}\"])\n // Get the latest entry\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Keep only the relevant columns\n |> keep(columns: [\"${unique_identifier}\", \"architecture\", \"soc\"])\n // Rename for clarity\n |> rename(columns: {\n architecture: \"Architecture\",\n soc: \"System on Chip\"\n })", + "refId": "A" + } + ], + "title": "Device Architecture & SoC", + "type": "stat" + }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, - "y": 16 + "y": 19 }, "id": 4, "panels": [], @@ -298,7 +360,7 @@ "h": 5, "w": 24, "x": 0, - "y": 17 + "y": 20 }, "id": 3, "options": { @@ -399,7 +461,7 @@ "h": 8, "w": 12, "x": 0, - "y": 22 + "y": 25 }, "id": 1, "options": { @@ -498,7 +560,7 @@ "h": 8, "w": 12, "x": 12, - "y": 22 + "y": 25 }, "id": 2, "options": { @@ -613,7 +675,7 @@ "h": 8, "w": 12, "x": 0, - "y": 30 + "y": 33 }, "id": 12, "options": { @@ -728,7 +790,7 @@ "h": 8, "w": 12, "x": 12, - "y": 30 + "y": 33 }, "id": 13, "options": { @@ -764,7 +826,7 @@ "h": 1, "w": 24, "x": 0, - "y": 38 + "y": 41 }, "id": 6, "panels": [], @@ -801,7 +863,7 @@ "h": 3, "w": 24, "x": 0, - "y": 39 + "y": 42 }, "id": 7, "options": { @@ -826,7 +888,7 @@ "type": "influxdb", "uid": "${datasource}" }, - "query": " // Get latest local and external IP per device in one query\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n // Select both relevant measurements\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"local_ip_addresses\" or\n r[\"_measurement\"] == \"external_ip\"\n )\n // Group by device and measurement\n |> group(columns: [\"${unique_identifier}\", \"_measurement\"])\n // Get the latest entry for each\n |> last()\n // Reshape for clarity\n |> pivot(\n rowKey: [\"${unique_identifier}\"],\n columnKey: [\"_measurement\"],\n valueColumn: \"_value\"\n )\n // Optional: Rename columns for clarity\n |> rename(columns: {\n local_ip_addresses: \"Local IPs\",\n external_ip: \"External IP\"\n })\n |> keep(columns: [\"${unique_identifier}\", \"Local IPs\", \"External IP\"])", + "query": " // Get latest local and external IP per device in one query\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n // Select both relevant measurements\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"local_ip_addresses\" or\n r[\"_measurement\"] == \"external_ip\"\n )\n // Group by device and measurement\n |> group(columns: [\"${unique_identifier}\", \"_measurement\"])\n // Get the latest entry for each\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Reshape for clarity\n |> pivot(\n rowKey: [\"${unique_identifier}\"],\n columnKey: [\"_measurement\"],\n valueColumn: \"_value\"\n )\n // Optional: Rename columns for clarity\n |> rename(columns: {\n local_ip_addresses: \"Local IPs\",\n external_ip: \"External IP\"\n })\n |> keep(columns: [\"${unique_identifier}\", \"Local IPs\", \"External IP\"])", "refId": "A" } ], @@ -897,7 +959,7 @@ "h": 10, "w": 24, "x": 0, - "y": 42 + "y": 45 }, "id": 8, "options": { @@ -991,7 +1053,7 @@ "h": 7, "w": 24, "x": 0, - "y": 52 + "y": 55 }, "id": 9, "options": { @@ -1112,5 +1174,5 @@ "timezone": "browser", "title": "Device Details", "uid": "bekds38txl1j4c", - "version": 36 + "version": 37 } diff --git a/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/overview_of_devices.json b/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/overview_of_devices.json index 80b9396..e680cd6 100644 --- a/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/overview_of_devices.json +++ b/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/overview_of_devices.json @@ -180,7 +180,7 @@ "targets": [ { "hide": false, - "query": "// Get devices with reported data in the selected interval\r\nfrom(bucket: \"${bucket}\")\r\n // Filter on time\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n // Filter using variable selectors (supports All and multi-select)\r\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\r\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\r\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\r\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\r\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\r\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\r\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\r\n // We cant flatten if the values are of different types, so we just\r\n // filter for an arbitrary value that we know exists...\r\n |> filter(fn: (r) =>\r\n r[\"_measurement\"] == \"cpu\" and\r\n r[\"cpu\"] == \"cpu-total\" and\r\n r[\"_field\"] == \"usage_idle\"\r\n )\r\n // Group by device to merge to one time series per device\r\n |> group(columns: [\"${unique_identifier}\"])\r\n // Get the last data point for each device. Note that last() does not work after\r\n // group, so we use sort+limit instead.\r\n |> sort(columns: [\"_time\"], desc: true)\r\n |> limit(n: 1)\r\n // Ungroup to prepare a flat output\r\n |> group()\r\n // Keep only timestamp and device identifier\r\n |> keep(columns: [\"_time\", \"${unique_identifier}\"])\r\n // Rename _time to seen\r\n |> rename(columns: {_time: \"seen\"})", + "query": "// Get devices with reported data in the selected interval\r\nfrom(bucket: \"${bucket}\")\r\n // Filter on time\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n // Filter using variable selectors (supports All and multi-select)\r\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\r\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\r\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\r\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\r\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\r\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\r\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\r\n // We cant flatten if the values are of different types, so we just\r\n // filter for an arbitrary value that we know exists...\r\n |> filter(fn: (r) =>\r\n r[\"_measurement\"] == \"cpu\" and\r\n r[\"cpu\"] == \"cpu-total\" and\r\n r[\"_field\"] == \"usage_idle\"\r\n )\r\n // Group by device to merge to one time series per device\r\n |> group(columns: [\"${unique_identifier}\"])\r\n // Get the last data point for each device. Note that last() does not work after\r\n // group, so we use sort+limit instead.\r\n |> sort(columns: [\"_time\"], desc: true)\r\n |> limit(n: 1)\r\n // Ungroup to prepare a flat output\r\n |> group()\r\n // Keep only timestamp and device identifier\r\n |> keep(columns: [\"_time\", \"${unique_identifier}\"])\r\n // Rename _time to seen\r\n |> rename(columns: {_time: \"seen\"})", "refId": "Get last time stamp" }, { @@ -189,7 +189,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "// Get latest external IP per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n // Filter on external IP measurement\n |> filter(fn: (r) => r[\"_measurement\"] == \"external_ip\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last reported external IP. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Rename the value column and keep only relevant fields\n |> rename(columns: {_value: \"external ip\"})\n |> keep(columns: [\"${unique_identifier}\", \"external ip\"])\n", + "query": "// Get latest external IP per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n // Filter on external IP measurement\n |> filter(fn: (r) => r[\"_measurement\"] == \"external_ip\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last reported external IP. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Rename the value column and keep only relevant fields\n |> rename(columns: {_value: \"external ip\"})\n |> keep(columns: [\"${unique_identifier}\", \"external ip\"])\n", "refId": "Get external IPs" }, { @@ -198,7 +198,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "// Get latest local IP per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n // Filter on local IP measurement\n |> filter(fn: (r) => r[\"_measurement\"] == \"local_ip_addresses\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last reported local IP. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Rename the value column and keep only relevant fields\n |> rename(columns: {_value: \"local ip\"})\n |> keep(columns: [\"${unique_identifier}\", \"local ip\"])\n", + "query": "// Get latest local IP per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n // Filter on local IP measurement\n |> filter(fn: (r) => r[\"_measurement\"] == \"local_ip_addresses\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last reported local IP. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Rename the value column and keep only relevant fields\n |> rename(columns: {_value: \"local ip\"})\n |> keep(columns: [\"${unique_identifier}\", \"local ip\"])\n", "refId": "Get internal IPs" }, { @@ -207,7 +207,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "// Get latest internet latency per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n // Filter on internet connectivity measurement and field\n |> filter(fn: (r) => r[\"_measurement\"] == \"internet_connectivity\")\n |> filter(fn: (r) => r[\"_field\"] == \"response_time\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last reported response time. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Rename the value column and keep only relevant fields\n |> rename(columns: {_value: \"internet latency\"})\n |> keep(columns: [\"${unique_identifier}\", \"internet latency\"])\n", + "query": "// Get latest internet latency per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n // Filter on internet connectivity measurement and field\n |> filter(fn: (r) => r[\"_measurement\"] == \"internet_connectivity\")\n |> filter(fn: (r) => r[\"_field\"] == \"response_time\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last reported response time. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Rename the value column and keep only relevant fields\n |> rename(columns: {_value: \"internet latency\"})\n |> keep(columns: [\"${unique_identifier}\", \"internet latency\"])\n", "refId": "Internet response time" }, { @@ -216,7 +216,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "// Get latest device model per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n // Filter on a single meaurement to make the schema aligned\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last report. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Keep only host and device model\n |> keep(columns: [\"${unique_identifier}\", \"product_full_name\"])\n |> rename(columns: {\n product_full_name: \"product full name\"\n })", + "query": "// Get latest device model per device in the selected interval\nfrom(bucket: \"${bucket}\")\n // Filter on time\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter using variable selectors (supports All and multi-select)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n // Filter on a single meaurement to make the schema aligned\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n // Group by device to isolate each host\n |> group(columns: [\"${unique_identifier}\"])\n // Get the last report. Note that last() does not work after\n // group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n // Ungroup to flatten result set\n |> group()\n // Keep only host and device model\n |> keep(columns: [\"${unique_identifier}\", \"product_full_name\"])\n |> rename(columns: {\n product_full_name: \"product full name\"\n })", "refId": "Get camera model name" }, { @@ -225,7 +225,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> group(columns: [\"${unique_identifier}\"])\n // Note that last() does not work after group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n |> group()\n |> keep(columns: [\"${unique_identifier}\", \"firmware_version\"])\n |> rename(columns: {\n firmware_version: \"firmware version\"\n })\n", + "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> group(columns: [\"${unique_identifier}\"])\n // Note that last() does not work after group, so we use sort+limit instead.\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n |> group()\n |> keep(columns: [\"${unique_identifier}\", \"firmware_version\"])\n |> rename(columns: {\n firmware_version: \"firmware version\"\n })\n", "refId": "A" } ], @@ -325,7 +325,7 @@ "pluginVersion": "12.0.2", "targets": [ { - "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // Generic measurement just to access the tags. To reduce number of points,\n // we also filter to one single core and field.\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n\n // Only show the ones that are reporting firmware_version\n exists r[\"firmware_version\"] and\n\n // Applied filters\n (r[\"area\"] =~ /^${area:regex}$/) and\n (r[\"geography\"] =~ /^${geography:regex}$/) and\n (r[\"region\"] =~ /^${region:regex}$/) and\n (r[\"site\"] =~ /^${site:regex}$/) and\n (r[\"type\"] =~ /^${type:regex}$/) and\n (r[\"${unique_identifier}\"] =~ /^${device:regex}$/) and\n (r[\"product_full_name\"] =~ /^${model:regex}$/)\n )\n\n // Aggregate into time series windows to reduce number of returned data points\n |> aggregateWindow(every: 1h, fn: last, createEmpty: false)\n\n // Keep timestamp, device and firmware_version\n |> keep(columns: [\"_time\", \"${unique_identifier}\", \"firmware_version\"])\n\n // Rename and remap to Grafana-friendly _time, _field, _value,\n // that gets rid of the \"firmware_version \" prefix in the visualization.\n |> map(fn: (r) => ({\n _time: r._time,\n _field: r[\"${unique_identifier}\"],\n _value: r[\"firmware_version\"]\n }))\n\n // Group per device (now in _field)\n |> group(columns: [\"_field\"])\n\n // Sort by time\n |> sort(columns: [\"_time\"])", + "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // Generic measurement just to access the tags. To reduce number of points,\n // we also filter to one single core and field.\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n\n // Only show the ones that are reporting firmware_version\n exists r[\"firmware_version\"] and\n\n // Applied filters\n (r[\"area\"] =~ /^${area:regex}$/) and\n (r[\"geography\"] =~ /^${geography:regex}$/) and\n (r[\"region\"] =~ /^${region:regex}$/) and\n (r[\"site\"] =~ /^${site:regex}$/) and\n (r[\"type\"] =~ /^${type:regex}$/) and\n (r[\"${unique_identifier}\"] =~ /^${device:regex}$/) and\n (r[\"product_full_name\"] =~ /^${model:regex}$/) and\n (r[\"architecture\"] =~ /^${architecture:regex}$/) and\n (r[\"soc\"] =~ /^${soc:regex}$/)\n )\n\n // Aggregate into time series windows to reduce number of returned data points\n |> aggregateWindow(every: 1h, fn: last, createEmpty: false)\n\n // Keep timestamp, device and firmware_version\n |> keep(columns: [\"_time\", \"${unique_identifier}\", \"firmware_version\"])\n\n // Rename and remap to Grafana-friendly _time, _field, _value,\n // that gets rid of the \"firmware_version \" prefix in the visualization.\n |> map(fn: (r) => ({\n _time: r._time,\n _field: r[\"${unique_identifier}\"],\n _value: r[\"firmware_version\"]\n }))\n\n // Group per device (now in _field)\n |> group(columns: [\"_field\"])\n\n // Sort by time\n |> sort(columns: [\"_time\"])", "refId": "A" } ], @@ -457,7 +457,7 @@ "type": "influxdb", "uid": "${datasource}" }, - "query": "from(bucket: \"${bucket}\")\n // Selected time span\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter based on drop-downs\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n // Filter out the fields we are interested in\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\n |> filter(fn: (r) => r[\"_field\"] == \"usage_idle\")\n // One time series for each device\n |> group(columns: [\"${unique_identifier}\"])\n // Invert to CPU load instead of idle\n |> map(fn: (r) => ({ r with _value: 100.0 - r._value }))\n // Aggregate in blocks to reduce number of data points\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)", + "query": "from(bucket: \"${bucket}\")\n // Selected time span\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter based on drop-downs\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n // Filter out the fields we are interested in\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\n |> filter(fn: (r) => r[\"_field\"] == \"usage_idle\")\n // One time series for each device\n |> group(columns: [\"${unique_identifier}\"])\n // Invert to CPU load instead of idle\n |> map(fn: (r) => ({ r with _value: 100.0 - r._value }))\n // Aggregate in blocks to reduce number of data points\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)", "refId": "cpu" }, { @@ -466,7 +466,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "from(bucket: \"${bucket}\")\n // Selected time span\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter based on drop-downs\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n // Filter out the fields we are interested in\n |> filter(fn: (r) => r[\"_measurement\"] == \"mem\")\n |> filter(fn: (r) => r[\"_field\"] == \"used_percent\")\n // One time series for each device\n |> group(columns: [\"${unique_identifier}\"])\n // Aggregate in blocks to reduce number of data points\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)", + "query": "from(bucket: \"${bucket}\")\n // Selected time span\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n // Filter based on drop-downs\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n // Filter out the fields we are interested in\n |> filter(fn: (r) => r[\"_measurement\"] == \"mem\")\n |> filter(fn: (r) => r[\"_field\"] == \"used_percent\")\n // One time series for each device\n |> group(columns: [\"${unique_identifier}\"])\n // Aggregate in blocks to reduce number of data points\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)", "refId": "ram" } ], @@ -1183,6 +1183,58 @@ "query": "bekds38txl1j4c", "skipUrlSync": true, "type": "constant" + }, + { + "current": { + "selected": true, + "text": ["All"], + "value": ["$__all"] + }, + "datasource": { + "type": "influxdb", + "uid": "${datasource}" + }, + "definition": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"architecture\", start: 1970-01-01T00:00:00Z)", + "hide": 0, + "includeAll": true, + "label": "Architecture", + "multi": true, + "name": "architecture", + "options": [], + "query": { + "query": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"architecture\", start: 1970-01-01T00:00:00Z)" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": ["All"], + "value": ["$__all"] + }, + "datasource": { + "type": "influxdb", + "uid": "${datasource}" + }, + "definition": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"soc\", start: 1970-01-01T00:00:00Z)", + "hide": 0, + "includeAll": true, + "label": "System on Chip", + "multi": true, + "name": "soc", + "options": [], + "query": { + "query": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"soc\", start: 1970-01-01T00:00:00Z)" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" } ] }, @@ -1194,5 +1246,5 @@ "timezone": "browser", "title": "Overview of Devices", "uid": "ceh7yyrnarj7kd", - "version": 32 + "version": 33 } diff --git a/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/system_overview.json b/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/system_overview.json index e87f504..6305391 100644 --- a/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/system_overview.json +++ b/dashboard-deployments/system-monitoring-influxdb2-flux-grafana/provisioning/dashboards/system_overview.json @@ -71,7 +71,7 @@ "pluginVersion": "12.0.2", "targets": [ { - "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\n |> keep(columns: [\"host\"])\n |> group()\n |> distinct(column: \"host\")\n |> count(column: \"_value\")\n |> rename(columns: {_value: \"total\"})\n |> yield(name: \"all\")\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\n |> keep(columns: [\"host\"])\n |> group()\n |> distinct(column: \"host\")\n |> count(column: \"_value\")\n |> rename(columns: {_value: \"selected\"})\n |> yield(name: \"filtered\")", + "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\n |> keep(columns: [\"host\"])\n |> group()\n |> distinct(column: \"host\")\n |> count(column: \"_value\")\n |> rename(columns: {_value: \"total\"})\n |> yield(name: \"all\")\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\n |> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\n |> keep(columns: [\"host\"])\n |> group()\n |> distinct(column: \"host\")\n |> count(column: \"_value\")\n |> rename(columns: {_value: \"selected\"})\n |> yield(name: \"filtered\")", "refId": "A" } ], @@ -225,7 +225,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "import \"array\"\n\n// Get cameras with reported data in the selected interval\nreal_data = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"type\"] =~ /^${type:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/\n )\n |> group(columns: [\"host\"])\n |> last()\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> rename(columns: {_time: \"seen\"})\n |> map(fn: (r) => ({ r with in_interval: true })) // Add extra field for easier identification\n\n// Dummy fallback row (ensures structure exists even if real data is empty)\nfake_row = array.from(rows: [\n {\n host: \"dummy_device\",\n seen: time(v: 0),\n in_interval: true,\n dummy: 1\n }\n])\n\n// Combine real data with dummy row\nunion(tables: [real_data, fake_row])", + "query": "import \"array\"\n\n// Get cameras with reported data in the selected interval\nreal_data = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"type\"] =~ /^${type:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"architecture\"] =~ /^${architecture:regex}$/ and\n r[\"soc\"] =~ /^${soc:regex}$/\n )\n |> group(columns: [\"host\"])\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> rename(columns: {_time: \"seen\"})\n |> map(fn: (r) => ({ r with in_interval: true })) // Add extra field for easier identification\n\n// Dummy fallback row (ensures structure exists even if real data is empty)\nfake_row = array.from(rows: [\n {\n host: \"dummy_device\",\n seen: time(v: 0),\n in_interval: true,\n dummy: 1\n }\n])\n\n// Combine real data with dummy row\nunion(tables: [real_data, fake_row])", "refId": "in-interval" }, { @@ -234,7 +234,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "import \"influxdata/influxdb/schema\"\n\n// Step 1: Get all known hosts\nhosts = schema.tagValues(\n bucket: \"${bucket}\",\n tag: \"host\"\n)\n |> rename(columns: {_value: \"host\"})\n |> map(fn: (r) => ({ r with known: true }))\n\n// Step 2: Get real data to apply tag-based filters\nfiltered_hosts = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n (exists r[\"area\"] and r[\"area\"] =~ /^${area:regex}$/) and\n (exists r[\"geography\"] and r[\"geography\"] =~ /^${geography:regex}$/) and\n (exists r[\"region\"] and r[\"region\"] =~ /^${region:regex}$/) and\n (exists r[\"site\"] and r[\"site\"] =~ /^${site:regex}$/) and\n (exists r[\"type\"] and r[\"type\"] =~ /^${type:regex}$/) and\n (exists r[\"${unique_identifier}\"] and r[\"${unique_identifier}\"] =~ /^${device:regex}$/) and\n (exists r[\"product_full_name\"] and r[\"product_full_name\"] =~ /^${model:regex}$/)\n )\n |> keep(columns: [\"host\"])\n |> group()\n |> distinct(column: \"host\")\n\n// Step 3: Join to retain only filtered hosts from schema list\njoin(\n tables: {all: hosts, filtered: filtered_hosts},\n on: [\"host\"]\n)\n", + "query": "import \"influxdata/influxdb/schema\"\n\n// Step 1: Get all known hosts\nhosts = schema.tagValues(\n bucket: \"${bucket}\",\n tag: \"host\"\n)\n |> rename(columns: {_value: \"host\"})\n |> map(fn: (r) => ({ r with known: true }))\n\n// Step 2: Get real data to apply tag-based filters\nfiltered_hosts = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n (exists r[\"area\"] and r[\"area\"] =~ /^${area:regex}$/) and\n (exists r[\"geography\"] and r[\"geography\"] =~ /^${geography:regex}$/) and\n (exists r[\"region\"] and r[\"region\"] =~ /^${region:regex}$/) and\n (exists r[\"site\"] and r[\"site\"] =~ /^${site:regex}$/) and\n (exists r[\"type\"] and r[\"type\"] =~ /^${type:regex}$/) and\n (exists r[\"${unique_identifier}\"] and r[\"${unique_identifier}\"] =~ /^${device:regex}$/) and\n (exists r[\"product_full_name\"] and r[\"product_full_name\"] =~ /^${model:regex}$/) and\n (exists r[\"architecture\"] and r[\"architecture\"] =~ /^${architecture:regex}$/) and\n (exists r[\"soc\"] and r[\"soc\"] =~ /^${soc:regex}$/)\n )\n |> keep(columns: [\"host\"])\n |> group()\n |> distinct(column: \"host\")\n\n// Step 3: Join to retain only filtered hosts from schema list\njoin(\n tables: {all: hosts, filtered: filtered_hosts},\n on: [\"host\"]\n)", "refId": "all_devices" }, { @@ -243,7 +243,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "// Get last timestamp from a host (check the last 3 months back)\nfrom(bucket: \"${bucket}\")\n |> range(start: -90d)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"type\"] =~ /^${type:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/\n )\n |> group(columns: [\"host\"])\n |> last()\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> rename(columns: {_time: \"last seen\"})\n |> map(fn: (r) => ({ r with seen_earlier: true })) // Add extra field for easier identification", + "query": "// Get last timestamp from a host (check the last 3 months back)\nfrom(bucket: \"${bucket}\")\n |> range(start: -90d)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\" and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"type\"] =~ /^${type:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"architecture\"] =~ /^${architecture:regex}$/ and\n r[\"soc\"] =~ /^${soc:regex}$/\n )\n |> group(columns: [\"host\"])\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> rename(columns: {_time: \"last seen\"})\n |> map(fn: (r) => ({ r with seen_earlier: true })) // Add extra field for easier identification", "refId": "last-seen" }, { @@ -252,7 +252,7 @@ "uid": "${datasource}" }, "hide": true, - "query": "// NOTE: This does not work as expected...\nfrom(bucket: \"${bucket}\")\n |> range(start: -90d)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\"\n )\n |> group(columns: [\"host\"])\n |> last()\n |> group()\n |> keep(columns: [\"host\", \"area\", \"geography\", \"region\", \"site\", \"type\", \"${unique_identifier}\", \"product_full_name\"])\n |> map(fn: (r) => ({\n host: r.host,\n filter_applies:\n (\n (r[\"area\"] =~ /^${area:regex}$/) and\n (r[\"geography\"] =~ /^${geography:regex}$/) and\n (r[\"region\"] =~ /^${region:regex}$/) and\n (r[\"site\"] =~ /^${site:regex}$/) and\n (r[\"type\"] =~ /^${type:regex}$/) and\n (r[\"${unique_identifier}\"] =~ /^${device:regex}$/) and\n (r[\"product_full_name\"] =~ /^${model:regex}$/)\n )\n }))\n", + "query": "// NOTE: This does not work as expected...\nfrom(bucket: \"${bucket}\")\n |> range(start: -90d)\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"cpu\" and\n r[\"cpu\"] == \"cpu-total\" and\n r[\"_field\"] == \"usage_idle\"\n )\n |> group(columns: [\"host\"])\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n |> group()\n |> keep(columns: [\"host\", \"area\", \"geography\", \"region\", \"site\", \"type\", \"${unique_identifier}\", \"product_full_name\", \"architecture\", \"soc\"])\n |> map(fn: (r) => ({\n host: r.host,\n filter_applies:\n (\n (r[\"area\"] =~ /^${area:regex}$/) and\n (r[\"geography\"] =~ /^${geography:regex}$/) and\n (r[\"region\"] =~ /^${region:regex}$/) and\n (r[\"site\"] =~ /^${site:regex}$/) and\n (r[\"type\"] =~ /^${type:regex}$/) and\n (r[\"${unique_identifier}\"] =~ /^${device:regex}$/) and\n (r[\"product_full_name\"] =~ /^${model:regex}$/) and\n (r[\"architecture\"] =~ /^${architecture:regex}$/) and\n (r[\"soc\"] =~ /^${soc:regex}$/)\n )\n }))", "refId": "filter applies" } ], @@ -480,7 +480,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "// Get cameras with reported data in the selected interval\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => (\n r[\"_measurement\"] == \"cpu\" and r[\"cpu\"] == \"cpu-total\" and r[\"_field\"] == \"usage_idle\"\n ))\n |> group(columns: [\"host\"])\n |> first()\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> rename(columns: {_time: \"first seen\"})\n |> map(fn: (r) => ({ r with in_interval: true })) // Add extra field for easier identification", + "query": "// Get cameras with reported data in the selected interval\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => (\n r[\"_measurement\"] == \"cpu\" and r[\"cpu\"] == \"cpu-total\" and r[\"_field\"] == \"usage_idle\" and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"type\"] =~ /^${type:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"architecture\"] =~ /^${architecture:regex}$/ and\n r[\"soc\"] =~ /^${soc:regex}$/\n ))\n |> group(columns: [\"host\"])\n |> first()\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> rename(columns: {_time: \"first seen\"})\n |> map(fn: (r) => ({ r with in_interval: true })) // Add extra field for easier identification", "refId": "in-interval" }, { @@ -489,7 +489,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "import \"array\"\nimport \"experimental\"\n\n// Make a query the last year before the selected interval starts,\n// that way we can find devices that was now known before the start of this\n// interval.\nbefore_data = from(bucket: \"${bucket}\")\n |> range(start: experimental.subDuration(from: v.timeRangeStart, d: 365d), stop: v.timeRangeStart) // Before the interval starts\n |> filter(fn: (r) => (\n r[\"_measurement\"] == \"cpu\" and r[\"cpu\"] == \"cpu-total\" and r[\"_field\"] == \"usage_idle\"\n ))\n |> group(columns: [\"host\"])\n |> last()\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> map(fn: (r) => ({ r with seen_earlier: true })) // Add extra field for easier identification\n\n// Dummy fallback row to ensure structure\nbefore_dummy =\n array.from(rows: [{\n host: \"dummy_device\",\n _time: time(v: 0),\n seen_earlier: true,\n dummy: 1\n }])\n\n// Combine real before data with fallback\nunion(tables: [before_data, before_dummy])", + "query": "import \"array\"\nimport \"experimental\"\n\n// Make a query the last year before the selected interval starts,\n// that way we can find devices that was now known before the start of this\n// interval.\nbefore_data = from(bucket: \"${bucket}\")\n |> range(start: experimental.subDuration(from: v.timeRangeStart, d: 365d), stop: v.timeRangeStart) // Before the interval starts\n |> filter(fn: (r) => (\n r[\"_measurement\"] == \"cpu\" and r[\"cpu\"] == \"cpu-total\" and r[\"_field\"] == \"usage_idle\" and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"type\"] =~ /^${type:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"architecture\"] =~ /^${architecture:regex}$/ and\n r[\"soc\"] =~ /^${soc:regex}$/\n ))\n |> group(columns: [\"host\"])\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1)\n |> group()\n |> keep(columns: [\"_time\", \"host\"])\n |> map(fn: (r) => ({ r with seen_earlier: true })) // Add extra field for easier identification\n\n// Dummy fallback row to ensure structure\nbefore_dummy =\n array.from(rows: [{\n host: \"dummy_device\",\n _time: time(v: 0),\n seen_earlier: true,\n dummy: 1\n }])\n\n// Combine real before data with fallback\nunion(tables: [before_data, before_dummy])", "refId": "before-interval" } ], @@ -682,7 +682,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "metric_to_use = \"load1\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Apply metadata filters first (only if fields exist)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n\n // 2. Then filter for the metric of interest\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"system\" and\n r[\"_field\"] == metric_to_use\n )\n\n // 3. Aggregate, format, and limit\n |> group(columns: [\"host\"])\n |> mean()\n |> group()\n |> rename(columns: {_value: metric_to_use})\n |> keep(columns: [\"host\", metric_to_use])\n |> sort(columns: [metric_to_use], desc: true)\n |> limit(n: ${outlier_count})\n", + "query": "metric_to_use = \"load1\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Apply metadata filters first (only if fields exist)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n\n // 2. Then filter for the metric of interest\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"system\" and\n r[\"_field\"] == metric_to_use\n )\n\n // 3. Aggregate, format, and limit\n |> group(columns: [\"host\"])\n |> mean()\n |> group()\n |> rename(columns: {_value: metric_to_use})\n |> keep(columns: [\"host\", metric_to_use])\n |> sort(columns: [metric_to_use], desc: true)\n |> limit(n: ${outlier_count})\n", "refId": "load1" }, { @@ -691,7 +691,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "metric_to_use = \"load15\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters (only if fields exist)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n\n // 2. Metric filtering\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"system\" and\n r[\"_field\"] == metric_to_use\n )\n\n // 3. Aggregation and formatting\n |> group(columns: [\"host\"])\n |> mean()\n |> group()\n |> rename(columns: {_value: metric_to_use})\n |> keep(columns: [\"host\", metric_to_use])\n\n // 4. Sort and limit\n |> sort(columns: [metric_to_use], desc: true)\n |> limit(n: ${outlier_count})\n", + "query": "metric_to_use = \"load15\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters (only if fields exist)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n\n // 2. Metric filtering\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"system\" and\n r[\"_field\"] == metric_to_use\n )\n\n // 3. Aggregation and formatting\n |> group(columns: [\"host\"])\n |> mean()\n |> group()\n |> rename(columns: {_value: metric_to_use})\n |> keep(columns: [\"host\", metric_to_use])\n\n // 4. Sort and limit\n |> sort(columns: [metric_to_use], desc: true)\n |> limit(n: ${outlier_count})\n", "refId": "load15" }, { @@ -700,7 +700,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "metric_to_use = \"uptime\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters (only apply if fields exist)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n\n // 2. Metric filter for uptime\n |> filter(fn: (r) => r[\"_measurement\"] == \"system\" and r[\"_field\"] == metric_to_use)\n\n // 3. Aggregate and format\n |> group(columns: [\"host\"])\n |> last() // Last reported uptime during the selected time span\n |> group()\n |> rename(columns: {_value: metric_to_use})\n |> keep(columns: [\"host\", metric_to_use])\n |> sort(columns: [metric_to_use], desc: false) // Ascending = lowest uptime\n |> limit(n: ${outlier_count})\n", + "query": "metric_to_use = \"uptime\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters (only apply if fields exist)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n\n // 2. Metric filter for uptime\n |> filter(fn: (r) => r[\"_measurement\"] == \"system\" and r[\"_field\"] == metric_to_use)\n\n // 3. Aggregate and format\n |> group(columns: [\"host\"])\n |> sort(columns: [\"_time\"], desc: true)\n |> limit(n: 1) // Last reported uptime during the selected time span\n |> group()\n |> rename(columns: {_value: metric_to_use})\n |> keep(columns: [\"host\", metric_to_use])\n |> sort(columns: [metric_to_use], desc: false) // Ascending = lowest uptime\n |> limit(n: ${outlier_count})\n", "refId": "uptime" }, { @@ -709,7 +709,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters (safe if tag missing)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n\n // 2. Metric filter\n |> filter(fn: (r) => r[\"_measurement\"] == \"mem\" and r[\"_field\"] == \"used_percent\")\n\n // 3. Aggregation and formatting\n |> group(columns: [\"host\"])\n |> mean()\n |> group()\n |> rename(columns: {_value: \"memory used\"})\n |> keep(columns: [\"host\", \"memory used\"])\n\n // 4. Sort by memory used (descending = highest usage)\n |> sort(columns: [\"memory used\"], desc: true)\n |> limit(n: ${outlier_count})\n", + "query": "from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters (safe if tag missing)\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n\n // 2. Metric filter\n |> filter(fn: (r) => r[\"_measurement\"] == \"mem\" and r[\"_field\"] == \"used_percent\")\n\n // 3. Aggregation and formatting\n |> group(columns: [\"host\"])\n |> mean()\n |> group()\n |> rename(columns: {_value: \"memory used\"})\n |> keep(columns: [\"host\", \"memory used\"])\n\n // 4. Sort by memory used (descending = highest usage)\n |> sort(columns: [\"memory used\"], desc: true)\n |> limit(n: ${outlier_count})\n", "refId": "memory" }, { @@ -718,7 +718,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "metric_name = \"flash used\"\ndisk_path = \"/usr/local\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n\n // 2. Metric and path filter\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"disk\" and\n r[\"_field\"] == \"used_percent\" and\n r[\"path\"] == disk_path\n )\n\n // 3. Aggregate and format\n |> group(columns: [\"host\"])\n |> mean() // Mean over the selected time span\n |> group()\n |> rename(columns: {_value: metric_name})\n |> keep(columns: [\"host\", metric_name])\n\n // 4. Sort and limit\n |> sort(columns: [metric_name], desc: true)\n |> limit(n: ${outlier_count})\n", + "query": "metric_name = \"flash used\"\ndisk_path = \"/usr/local\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n\n // 2. Metric and path filter\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"disk\" and\n r[\"_field\"] == \"used_percent\" and\n r[\"path\"] == disk_path\n )\n\n // 3. Aggregate and format\n |> group(columns: [\"host\"])\n |> mean() // Mean over the selected time span\n |> group()\n |> rename(columns: {_value: metric_name})\n |> keep(columns: [\"host\", metric_name])\n\n // 4. Sort and limit\n |> sort(columns: [metric_name], desc: true)\n |> limit(n: ${outlier_count})\n", "refId": "flash" }, { @@ -727,7 +727,7 @@ "uid": "${datasource}" }, "hide": false, - "query": "metric_name = \"sd card used\"\ndisk_path = \"/var/spool/storage/SD_DISK\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n\n // 2. Metric and path filter\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"disk\" and\n r[\"_field\"] == \"used_percent\" and\n r[\"path\"] == disk_path\n )\n\n // 3. Aggregate and format\n |> group(columns: [\"host\"])\n |> mean() // Mean over the selected time span\n |> group()\n |> rename(columns: {_value: metric_name})\n |> keep(columns: [\"host\", metric_name])\n\n // 4. Sort and limit\n |> sort(columns: [metric_name], desc: true)\n |> limit(n: ${outlier_count})\n", + "query": "metric_name = \"sd card used\"\ndisk_path = \"/var/spool/storage/SD_DISK\"\n\nfrom(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n\n // 1. Metadata filters\n |> filter(fn: (r) => r[\"area\"] =~ /^${area:regex}$/)\n |> filter(fn: (r) => r[\"geography\"] =~ /^${geography:regex}$/)\n |> filter(fn: (r) => r[\"region\"] =~ /^${region:regex}$/)\n |> filter(fn: (r) => r[\"site\"] =~ /^${site:regex}$/)\n |> filter(fn: (r) => r[\"type\"] =~ /^${type:regex}$/)\n |> filter(fn: (r) => r[\"${unique_identifier}\"] =~ /^${device:regex}$/)\n |> filter(fn: (r) => r[\"product_full_name\"] =~ /^${model:regex}$/)\n |> filter(fn: (r) => r[\"architecture\"] =~ /^${architecture:regex}$/)\n |> filter(fn: (r) => r[\"soc\"] =~ /^${soc:regex}$/)\n\n // 2. Metric and path filter\n |> filter(fn: (r) =>\n r[\"_measurement\"] == \"disk\" and\n r[\"_field\"] == \"used_percent\" and\n r[\"path\"] == disk_path\n )\n\n // 3. Aggregate and format\n |> group(columns: [\"host\"])\n |> mean() // Mean over the selected time span\n |> group()\n |> rename(columns: {_value: metric_name})\n |> keep(columns: [\"host\", metric_name])\n\n // 4. Sort and limit\n |> sort(columns: [metric_name], desc: true)\n |> limit(n: ${outlier_count})\n", "refId": "SD card" } ], @@ -843,7 +843,7 @@ "pluginVersion": "12.0.2", "targets": [ { - "query": "cpu = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"cpu\" and\n r._field == \"usage_idle\" and\n r.cpu == \"cpu-total\" and\n exists r.type and\n r.type =~ /^${type:regex}$/ and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/\n )\n |> map(fn: (r) => ({ r with _value: 100.0 - r._value }))\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"CPU Usage\" }))\n\nram = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"mem\" and\n r._field == \"used_percent\" and\n exists r.type and\n r.type =~ /^${type:regex}$/ and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/\n )\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"RAM Usage\" }))\n\ndisk_usr_local = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"disk\" and\n r._field == \"used_percent\" and\n r.path == \"/usr/local\" and\n exists r.type and\n r.type =~ /^${type:regex}$/ and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/\n )\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"Disk /usr/local\" }))\n\ndisk_sd = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n r._measurement == \"disk\" and\n r._field == \"used_percent\" and\n r.path == \"/var/volatile/spool/storage/SD_DISK\" and\n exists r.type and\n r.type =~ /^${type:regex}$/ and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/\n )\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"Disk /SD_DISK\" }))\n\nunion(tables: [cpu, ram, disk_usr_local, disk_sd])\n |> group()\n |> pivot(rowKey: [\"type\"], columnKey: [\"metric\"], valueColumn: \"_value\")\n", + "query": "// Base query with shared filters\nbase_data = from(bucket: \"${bucket}\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) =>\n exists r.type and\n r.type =~ /^${type:regex}$/ and\n r[\"area\"] =~ /^${area:regex}$/ and\n r[\"geography\"] =~ /^${geography:regex}$/ and\n r[\"region\"] =~ /^${region:regex}$/ and\n r[\"site\"] =~ /^${site:regex}$/ and\n r[\"product_full_name\"] =~ /^${model:regex}$/ and\n r[\"${unique_identifier}\"] =~ /^${device:regex}$/ and\n r[\"architecture\"] =~ /^${architecture:regex}$/ and\n r[\"soc\"] =~ /^${soc:regex}$/\n )\n\n// CPU usage per type\ncpu = base_data\n |> filter(fn: (r) =>\n r._measurement == \"cpu\" and\n r._field == \"usage_idle\" and\n r.cpu == \"cpu-total\"\n )\n |> map(fn: (r) => ({ r with _value: 100.0 - r._value }))\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"CPU Usage\" }))\n\n// RAM usage per type\nram = base_data\n |> filter(fn: (r) =>\n r._measurement == \"mem\" and\n r._field == \"used_percent\"\n )\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"RAM Usage\" }))\n\n// Built-in storage usage per type\ndisk_usr_local = base_data\n |> filter(fn: (r) =>\n r._measurement == \"disk\" and\n r._field == \"used_percent\" and\n r.path == \"/usr/local\"\n )\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"Disk /usr/local\" }))\n\n// SD card storage usage per type\ndisk_sd = base_data\n |> filter(fn: (r) =>\n r._measurement == \"disk\" and\n r._field == \"used_percent\" and\n r.path == \"/var/volatile/spool/storage/SD_DISK\"\n )\n |> group(columns: [\"type\"])\n |> mean()\n |> map(fn: (r) => ({ r with metric: \"Disk /SD_DISK\" }))\n\n// Combine all metrics into a single table\nunion(tables: [cpu, ram, disk_usr_local, disk_sd])\n |> group()\n |> pivot(rowKey: [\"type\"], columnKey: [\"metric\"], valueColumn: \"_value\")", "refId": "A" } ], @@ -1137,6 +1137,56 @@ "query": "1,2,3,4,5,10,50", "type": "custom" }, + { + "allValue": ".*", + "allowCustomValue": false, + "current": { + "text": "All", + "value": ["$__all"] + }, + "datasource": { + "type": "influxdb", + "uid": "${datasource}" + }, + "definition": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"architecture\", start: 1970-01-01T00:00:00Z)", + "includeAll": true, + "label": "Architecture", + "multi": true, + "name": "architecture", + "options": [], + "query": { + "query": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"architecture\", start: 1970-01-01T00:00:00Z)" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "allValue": ".*", + "allowCustomValue": false, + "current": { + "text": "All", + "value": ["$__all"] + }, + "datasource": { + "type": "influxdb", + "uid": "${datasource}" + }, + "definition": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"soc\", start: 1970-01-01T00:00:00Z)", + "includeAll": true, + "label": "System on Chip", + "multi": true, + "name": "soc", + "options": [], + "query": { + "query": "import \"influxdata/influxdb/schema\"\n\nschema.tagValues(bucket: \"${bucket}\", tag: \"soc\", start: 1970-01-01T00:00:00Z)" + }, + "refresh": 1, + "regex": "", + "sort": 1, + "type": "query" + }, { "current": { "text": "bekds38txl1j4c", @@ -1159,5 +1209,5 @@ "timezone": "browser", "title": "System Overview", "uid": "dsdsadfg3t3t3", - "version": 28 + "version": 29 }