From 71fa9847bbfab581baeb197ebf2aa1b4eb5f9646 Mon Sep 17 00:00:00 2001 From: ahinvinith Date: Thu, 9 Nov 2023 17:46:08 +0530 Subject: [PATCH] Dashboard modifications --- charts/client/Chart.yaml | 2 +- .../templates/configmap-azure-dashboard.yaml | 31 +- .../configmap-bitbucket-dashboard.yaml | 16 +- .../templates/configmap-gitea-dashboard.yaml | 19 +- .../templates/configmap-github-dashboard.yaml | 22 +- .../templates/configmap-gitlab-dashboard.yaml | 36 +- .../configmap-kubedata-dashboard.yaml | 254 ++++++++- .../templates/configmap-kubviz-dashboard.yaml | 505 ++++++++++++++--- grafana/azure-dashboard.json | 31 +- grafana/bitBucket-dashboard.json | 16 +- grafana/giTea-dashboard.json | 19 +- grafana/gitHub-dashboard.json | 22 +- grafana/gitLab-dashboard.json | 36 +- grafana/kubeData-dashboard.json | 254 ++++++++- grafana/kubvizDsahboard.json | 507 +++++++++++++++--- 15 files changed, 1452 insertions(+), 318 deletions(-) diff --git a/charts/client/Chart.yaml b/charts/client/Chart.yaml index a7d900bb..c2a5d128 100644 --- a/charts/client/Chart.yaml +++ b/charts/client/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.1.8 +version: 1.1.9 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/client/templates/configmap-azure-dashboard.yaml b/charts/client/templates/configmap-azure-dashboard.yaml index f0bfca39..ea290c78 100644 --- a/charts/client/templates/configmap-azure-dashboard.yaml +++ b/charts/client/templates/configmap-azure-dashboard.yaml @@ -26,7 +26,7 @@ data: "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 12, + "id": 33, "links": [], "liveNow": false, "panels": [ @@ -55,7 +55,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -114,7 +114,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -173,7 +173,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -223,8 +223,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -294,8 +293,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -372,8 +370,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" } ] } @@ -429,11 +426,7 @@ data: "templating": { "list": [ { - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, + "current": {}, "datasource": { "type": "vertamedia-clickhouse-datasource", "uid": "{{ .Values.datasources.uid }}" @@ -452,11 +445,7 @@ data: "type": "query" }, { - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, + "current": {}, "datasource": { "type": "vertamedia-clickhouse-datasource", "uid": "{{ .Values.datasources.uid }}" @@ -484,7 +473,7 @@ data: "timezone": "", "title": "Azure", "uid": "dd66838a-ffda-4de2-944f-1828d1671fc9", - "version": 2, + "version": 1, "weekStart": "" } {{- end }} \ No newline at end of file diff --git a/charts/client/templates/configmap-bitbucket-dashboard.yaml b/charts/client/templates/configmap-bitbucket-dashboard.yaml index 04a61d88..fde60b9f 100644 --- a/charts/client/templates/configmap-bitbucket-dashboard.yaml +++ b/charts/client/templates/configmap-bitbucket-dashboard.yaml @@ -26,7 +26,7 @@ data: "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 13, + "id": 34, "links": [], "liveNow": false, "panels": [ @@ -55,7 +55,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -114,7 +114,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -173,7 +173,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -223,8 +223,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -294,8 +293,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -483,7 +481,7 @@ data: "timezone": "", "title": "BitBucket", "uid": "a7772dd5-76c7-48f3-8462-b39fbc20941c", - "version": 2, + "version": 1, "weekStart": "" } {{- end }} \ No newline at end of file diff --git a/charts/client/templates/configmap-gitea-dashboard.yaml b/charts/client/templates/configmap-gitea-dashboard.yaml index db0eca73..3c1a663f 100644 --- a/charts/client/templates/configmap-gitea-dashboard.yaml +++ b/charts/client/templates/configmap-gitea-dashboard.yaml @@ -26,7 +26,7 @@ data: "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 11, + "id": 35, "links": [], "liveNow": false, "panels": [ @@ -55,7 +55,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -114,7 +114,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -173,7 +173,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -223,8 +223,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -294,8 +293,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -372,8 +370,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" } ] } @@ -484,7 +481,7 @@ data: "timezone": "", "title": "GiTea", "uid": "a1c6d705-91b0-4718-99b2-d93b0221bca9", - "version": 2, + "version": 1, "weekStart": "" } {{- end }} \ No newline at end of file diff --git a/charts/client/templates/configmap-github-dashboard.yaml b/charts/client/templates/configmap-github-dashboard.yaml index 9373cd00..860f77a1 100644 --- a/charts/client/templates/configmap-github-dashboard.yaml +++ b/charts/client/templates/configmap-github-dashboard.yaml @@ -26,7 +26,7 @@ data: "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 10, + "id": 37, "links": [], "liveNow": false, "panels": [ @@ -55,7 +55,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}", "google": { "callback": "gmapReady", "key": "" @@ -115,7 +115,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;\n\n", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -174,7 +174,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -407,8 +407,8 @@ data: { "current": { "selected": false, - "text": "All", - "value": "$__all" + "text": "", + "value": "" }, "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -429,9 +429,13 @@ data: }, { "current": { - "selected": false, - "text": "All", - "value": "$__all" + "selected": true, + "text": [ + "push" + ], + "value": [ + "push" + ] }, "datasource": { "type": "vertamedia-clickhouse-datasource", diff --git a/charts/client/templates/configmap-gitlab-dashboard.yaml b/charts/client/templates/configmap-gitlab-dashboard.yaml index 382d3e04..bc1273b7 100644 --- a/charts/client/templates/configmap-gitlab-dashboard.yaml +++ b/charts/client/templates/configmap-gitlab-dashboard.yaml @@ -26,7 +26,7 @@ data: "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 14, + "id": 36, "links": [], "liveNow": false, "panels": [ @@ -55,7 +55,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -114,7 +114,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -173,7 +173,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -223,8 +223,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -294,8 +293,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -433,13 +431,9 @@ data: "list": [ { "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "selected": false, + "text": "All", + "value": "$__all" }, "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -460,13 +454,9 @@ data: }, { "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "selected": false, + "text": "All", + "value": "$__all" }, "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -495,7 +485,7 @@ data: "timezone": "", "title": "GitLab", "uid": "ec8b9cb1-f9ae-4139-b270-4824b6508eff", - "version": 2, + "version": 1, "weekStart": "" } {{- end }} \ No newline at end of file diff --git a/charts/client/templates/configmap-kubedata-dashboard.yaml b/charts/client/templates/configmap-kubedata-dashboard.yaml index ff4b9e7c..9a263900 100644 --- a/charts/client/templates/configmap-kubedata-dashboard.yaml +++ b/charts/client/templates/configmap-kubedata-dashboard.yaml @@ -32,7 +32,7 @@ data: "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 9, + "id": 31, "links": [], "liveNow": false, "panels": [ @@ -42,11 +42,247 @@ data: "uid": "{{ .Values.datasources.uid }}" }, "gridPos": { - "h": 11, + "h": 14, "w": 24, "x": 0, "y": 0 }, + "id": 6, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND ClusterName IN ($clusterName) AND Kind IN ('Pod', 'Node', 'Deployment')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "rawQuery": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE EventTime >= toDateTime(1698927439) AND EventTime <= toDateTime(1698927739) AND ClusterName IN ('beta-cluster') AND Kind IN ('Pod', 'Node', 'Deployment')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "K8s metrics status", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 8, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND ClusterName IN ($clusterName) AND Kind IN ('Service')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "rawQuery": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE EventTime >= toDateTime(1698931712) AND EventTime <= toDateTime(1698932012) AND ClusterName IN ('beta-cluster') AND Kind IN ('Service')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Service Events by Cluster and Reason", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 9, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);\n\n", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND Kind IN ('PersistentVolume','PersistentVolumeClaim')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC\n", + "rawQuery": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE EventTime >= toDateTime(1698931738) AND EventTime <= toDateTime(1698932038) AND Kind IN ('PersistentVolume','PersistentVolumeClaim')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "PV, PVC events by cluster and reason", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 7, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Extract data from your JSON\n const clusters = data.series[0].fields[0].values;\n const hosts = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const eventTimes = data.series[0].fields[3].values;\n\n // Create a hierarchical structure for the tree chart starting with ClusterName\n const hierarchy = {\n name: 'Cluster Hierarchy',\n children: [],\n };\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i];\n const host = hosts[i];\n const reason = reasons[i];\n const eventTime = eventTimes[i];\n\n // Find or create the cluster node\n let clusterNode = hierarchy.children.find((node) => node.name === cluster);\n if (!clusterNode) {\n clusterNode = { name: cluster, children: [] };\n hierarchy.children.push(clusterNode);\n }\n\n // Find or create the host node under the cluster\n let hostNode = clusterNode.children.find((node) => node.name === host);\n if (!hostNode) {\n hostNode = { name: host, children: [] };\n clusterNode.children.push(hostNode);\n }\n\n // Find or create the reason node under the host\n let reasonNode = hostNode.children.find((node) => node.name === reason);\n if (!reasonNode) {\n reasonNode = { name: reason, children: [] };\n hostNode.children.push(reasonNode);\n }\n\n // Create the eventTime node under the reason\n reasonNode.children.push({ name: eventTime });\n }\n\n // Create the tree chart using ECharts\n const option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Start directly from the Cluster Hierarchy node\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%', // Adjust the right margin to provide more space for labels\n symbolSize: 7,\n label: {\n position: 'inside', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'center', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n leaves: {\n label: {\n position: 'right', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'left', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\nreturn option;", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Host, Reason, EventTime\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND ClusterName IN ($clusterName) AND Kind = 'Node' AND Kind != ' '\nGROUP BY ClusterName, Host, Reason, EventTime", + "rawQuery": "SELECT ClusterName, Host, Reason, EventTime\nFROM default.events\nWHERE EventTime >= toDateTime(1698927382) AND EventTime <= toDateTime(1698927682) AND ClusterName IN ('beta-cluster') AND Kind = 'Node' AND Kind != ' '\nGROUP BY ClusterName, Host, Reason, EventTime", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Node Events by Cluster, Host, Reason, and EventTime", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 35 + }, "id": 5, "options": { "baidu": { @@ -61,7 +297,7 @@ data: "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract data from your JSON\nconst clusterNames = data.series[0].fields[0].values; // New column for ClusterName\nconst namespaces = data.series[0].fields[1].values;\nconst kinds = data.series[0].fields[2].values; // Adjusted index for Kind\nconst counts = data.series[0].fields[3].values; // New column for Count\n\n// Create a hierarchical structure from the data without a root node\nconst hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n};\n\nconst seenClusterNames = new Set();\nconst seenNamespaces = new Set();\n\nfor (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n}\n\n// Create the tree chart using ECharts\nconst option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n};\nreturn option;", + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = data.series[0].fields[0].values; // New column for ClusterName\n const namespaces = data.series[0].fields[1].values;\n const kinds = data.series[0].fields[2].values; // Adjusted index for Kind\n const counts = data.series[0].fields[3].values; // New column for Count\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -112,8 +348,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -128,7 +363,7 @@ data: "h": 7, "w": 24, "x": 0, - "y": 11 + "y": 46 }, "id": 4, "options": { @@ -191,8 +426,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -207,7 +441,7 @@ data: "h": 16, "w": 24, "x": 0, - "y": 18 + "y": 53 }, "id": 2, "options": { @@ -353,7 +587,7 @@ data: "timezone": "", "title": "Kubedata", "uid": "Qq-FK1rVz", - "version": 2, + "version": 1, "weekStart": "" } {{- end }} \ No newline at end of file diff --git a/charts/client/templates/configmap-kubviz-dashboard.yaml b/charts/client/templates/configmap-kubviz-dashboard.yaml index c79ea4bb..6ee2c56c 100644 --- a/charts/client/templates/configmap-kubviz-dashboard.yaml +++ b/charts/client/templates/configmap-kubviz-dashboard.yaml @@ -32,7 +32,7 @@ data: "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 126, + "id": 32, "links": [], "liveNow": false, "panels": [ @@ -184,6 +184,381 @@ data: "title": "Clusters with Most Activity", "type": "gauge" }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "gridPos": { + "h": 9, + "w": 13, + "x": 0, + "y": 6 + }, + "id": 72, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const reasons = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const eventTimes = data.series[0].fields[2].values;\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n reasons.forEach((reason, index) => {\n const sourceNode = {\n name: reason,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const kindNode = {\n name: kinds[index],\n category: 1, // Category for kind nodes\n symbolSize: 40, // Size for kind nodes\n };\n\n const eventTimeNode = {\n name: eventTimes[index],\n category: 2, // Category for eventTime nodes\n symbolSize: 20, // Size for eventTime nodes\n };\n\n // Ensure source, kind, and eventTime nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === kindNode.name)) {\n nodes.push(kindNode);\n }\n\n if (!nodes.some((node) => node.name === eventTimeNode.name)) {\n nodes.push(eventTimeNode);\n }\n\n // Create links between reason, kind, and eventTime nodes\n links.push({\n source: reason,\n target: kinds[index],\n });\n\n links.push({\n source: kinds[index],\n target: eventTimes[index],\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Reasons',\n },\n {\n name: 'Nodes',\n },\n {\n name: 'Event Times',\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Reasons', 'Nodes', 'Event Times'],\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: {\n color: '#000',\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n edgeSymbolSize: [12, 12],\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT Reason, Host, EventTime\nFROM default.events\nWHERE Kind IN ('Node') AND Reason IN ('NodeNotReady')", + "rawQuery": "SELECT Reason, Host, EventTime\nFROM default.events\nWHERE Kind IN ('Node') AND Reason IN ('NodeNotReady')", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "NodeNotReady Events for Nodes", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "gridPos": { + "h": 9, + "w": 11, + "x": 13, + "y": 6 + }, + "id": 70, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let kind = [];\nlet resources = [];\n\ndata.series.map((s) => {\n kind = s.fields.find((f) => f.name === 'Kind').values;\n resources = s.fields.find((f) => f.name === 'Resources').values;\n});\n\n// Create an empty array to store doughnut chart data\nconst doughnutChartData = [];\n\n// Define colors for doughnut slices\nconst doughnutSliceColors = ['#235894', '#FFFF00', '#FF0000', '#00FF00', '#FFA500'];\n\n// Map severity and counts to doughnut chart data\nkind.forEach((kinddata, index) => {\n doughnutChartData.push({\n value: resources[index],\n name: kinddata,\n itemStyle: {\n borderRadius: [10, 10, 10, 10], // Add rounded corners\n color: doughnutSliceColors[index % doughnutSliceColors.length],\n borderWidth: 2,\n borderColor: '#fff',\n },\n });\n});\n\nreturn {\n backgroundColor: '#FFFFFF', // Set the background color to white\n tooltip: {\n trigger: 'item',\n },\n legend: {\n top: '5%',\n left: 'center',\n },\n series: [\n {\n name: 'Access From',\n type: 'pie',\n radius: ['40%', '70%'],\n avoidLabelOverlap: false,\n label: {\n show: false,\n position: 'center',\n },\n emphasis: {\n label: {\n show: true,\n fontSize: 40,\n fontWeight: 'bold',\n },\n },\n labelLine: {\n show: false,\n },\n data: doughnutChartData, // Use the modified doughnut chart data\n },\n ],\n};", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, count(Resource) AS Resources\nFROM default.getall_resources\nWHERE $timeFilterByColumn(EventTime) AND Kind In ('Deployment','Job','Secret', 'ConfigMap', 'Service')\nGROUP BY ClusterName, Kind", + "rawQuery": "SELECT ClusterName, Kind, count(Resource) AS Resources\nFROM default.getall_resources\nWHERE EventTime >= toDateTime(1698841487) AND EventTime <= toDateTime(1698927887) AND Kind In ('Deployment','Job','Secret', 'ConfigMap', 'Service')\nGROUP BY ClusterName, Kind", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Resource Distribution", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 30, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 15 + }, + "id": 69, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": " SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'Created'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'Created'\n GROUP BY EventTime, Kind, Reason", + "refId": "A", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": " SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'BackOff'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'BackOff'\n GROUP BY EventTime, Kind, Reason", + "refId": "B", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'NodeNotReady'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'NodeNotReady'\n GROUP BY EventTime, Kind, Reason", + "refId": "C", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": " SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'Scheduled'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'Scheduled'\n GROUP BY EventTime, Kind, Reason", + "refId": "D", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'FailedScheduling'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'FailedScheduling'\n GROUP BY EventTime, Kind, Reason", + "refId": "E", + "round": "0s", + "skip_comments": true + } + ], + "title": "Pod Events by Reason Over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "center", + "cellOptions": { + "type": "color-text" + }, + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Age" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 15 + }, + "id": 71, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "{{ .Values.datasources.uid }}" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Resource, Age\nFROM default.getall_resources\nWHERE $timeFilterByColumn(EventTime)", + "rawQuery": "SELECT ClusterName, Resource, Age\nFROM default.getall_resources\nWHERE EventTime >= toDateTime(1696336208) AND EventTime <= toDateTime(1698928208)", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Resource Details by Cluster and Age", + "type": "table" + }, { "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -217,7 +592,7 @@ data: "h": 4, "w": 5, "x": 0, - "y": 6 + "y": 22 }, "id": 18, "options": { @@ -287,7 +662,7 @@ data: "h": 4, "w": 5, "x": 5, - "y": 6 + "y": 22 }, "id": 20, "options": { @@ -357,7 +732,7 @@ data: "h": 4, "w": 5, "x": 10, - "y": 6 + "y": 22 }, "id": 22, "options": { @@ -427,7 +802,7 @@ data: "h": 4, "w": 5, "x": 15, - "y": 6 + "y": 22 }, "id": 24, "options": { @@ -497,7 +872,7 @@ data: "h": 4, "w": 4, "x": 20, - "y": 6 + "y": 22 }, "id": 26, "options": { @@ -600,7 +975,7 @@ data: "h": 6, "w": 13, "x": 0, - "y": 10 + "y": 26 }, "id": 53, "options": { @@ -701,7 +1076,7 @@ data: "h": 6, "w": 11, "x": 13, - "y": 10 + "y": 26 }, "id": 65, "options": { @@ -757,8 +1132,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -773,7 +1147,7 @@ data: "h": 4, "w": 6, "x": 0, - "y": 16 + "y": 32 }, "id": 57, "options": { @@ -826,8 +1200,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -846,7 +1219,7 @@ data: "h": 4, "w": 6, "x": 6, - "y": 16 + "y": 32 }, "id": 63, "options": { @@ -897,8 +1270,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -917,7 +1289,7 @@ data: "h": 4, "w": 6, "x": 12, - "y": 16 + "y": 32 }, "id": 61, "options": { @@ -968,8 +1340,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -988,7 +1359,7 @@ data: "h": 4, "w": 6, "x": 18, - "y": 16 + "y": 32 }, "id": 62, "options": { @@ -1043,8 +1414,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1059,7 +1429,7 @@ data: "h": 4, "w": 6, "x": 0, - "y": 20 + "y": 36 }, "id": 56, "options": { @@ -1112,8 +1482,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1132,7 +1501,7 @@ data: "h": 4, "w": 6, "x": 6, - "y": 20 + "y": 36 }, "id": 58, "options": { @@ -1183,8 +1552,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1203,7 +1571,7 @@ data: "h": 4, "w": 6, "x": 12, - "y": 20 + "y": 36 }, "id": 59, "options": { @@ -1254,8 +1622,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1274,7 +1641,7 @@ data: "h": 4, "w": 6, "x": 18, - "y": 20 + "y": 36 }, "id": 60, "options": { @@ -1336,8 +1703,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "light-yellow", @@ -1381,7 +1747,7 @@ data: "h": 8, "w": 24, "x": 0, - "y": 24 + "y": 40 }, "id": 44, "options": { @@ -1435,8 +1801,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1455,7 +1820,7 @@ data: "h": 5, "w": 8, "x": 0, - "y": 32 + "y": 48 }, "id": 66, "options": { @@ -1505,8 +1870,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1525,7 +1889,7 @@ data: "h": 5, "w": 8, "x": 8, - "y": 32 + "y": 48 }, "id": 68, "options": { @@ -1575,8 +1939,7 @@ data: "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1595,7 +1958,7 @@ data: "h": 5, "w": 8, "x": 16, - "y": 32 + "y": 48 }, "id": 67, "options": { @@ -1657,8 +2020,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1690,7 +2052,7 @@ data: "h": 8, "w": 24, "x": 0, - "y": 37 + "y": 53 }, "id": 64, "options": { @@ -1766,8 +2128,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1782,7 +2143,7 @@ data: "h": 9, "w": 12, "x": 0, - "y": 45 + "y": 61 }, "id": 34, "options": { @@ -1866,8 +2227,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1882,7 +2242,7 @@ data: "h": 9, "w": 12, "x": 12, - "y": 45 + "y": 61 }, "id": 36, "options": { @@ -1966,8 +2326,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1982,7 +2341,7 @@ data: "h": 8, "w": 8, "x": 0, - "y": 54 + "y": 70 }, "id": 28, "options": { @@ -2065,8 +2424,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2081,7 +2439,7 @@ data: "h": 8, "w": 8, "x": 8, - "y": 54 + "y": 70 }, "id": 32, "options": { @@ -2165,8 +2523,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2181,7 +2538,7 @@ data: "h": 8, "w": 8, "x": 16, - "y": 54 + "y": 70 }, "id": 30, "options": { @@ -2251,8 +2608,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "light-yellow", @@ -2288,7 +2644,7 @@ data: "h": 7, "w": 24, "x": 0, - "y": 62 + "y": 78 }, "id": 42, "options": { @@ -2335,7 +2691,7 @@ data: "h": 1, "w": 24, "x": 0, - "y": 69 + "y": 85 }, "id": 16, "panels": [ @@ -2363,8 +2719,7 @@ data: "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2379,7 +2734,7 @@ data: "h": 16, "w": 24, "x": 0, - "y": 70 + "y": 110 }, "id": 14, "options": { @@ -2440,7 +2795,7 @@ data: "h": 1, "w": 24, "x": 0, - "y": 70 + "y": 86 }, "id": 12, "panels": [ @@ -2482,7 +2837,7 @@ data: "h": 16, "w": 24, "x": 0, - "y": 87 + "y": 127 }, "id": 10, "options": { @@ -2543,7 +2898,7 @@ data: "h": 1, "w": 24, "x": 0, - "y": 71 + "y": 87 }, "id": 8, "panels": [ @@ -2586,7 +2941,7 @@ data: "h": 11, "w": 24, "x": 0, - "y": 72 + "y": 112 }, "id": 6, "options": { @@ -2647,7 +3002,7 @@ data: "h": 1, "w": 24, "x": 0, - "y": 72 + "y": 88 }, "id": 4, "panels": [ @@ -2690,7 +3045,7 @@ data: "h": 8, "w": 24, "x": 0, - "y": 73 + "y": 113 }, "id": 2, "options": { diff --git a/grafana/azure-dashboard.json b/grafana/azure-dashboard.json index a634cc28..bea62afc 100644 --- a/grafana/azure-dashboard.json +++ b/grafana/azure-dashboard.json @@ -15,7 +15,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 12, + "id": 33, "links": [], "liveNow": false, "panels": [ @@ -44,7 +44,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -103,7 +103,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -162,7 +162,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -212,8 +212,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -283,8 +282,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -361,8 +359,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" } ] } @@ -418,11 +415,7 @@ "templating": { "list": [ { - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, + "current": {}, "datasource": { "type": "vertamedia-clickhouse-datasource", "uid": "vertamedia-clickhouse-datasource" @@ -441,11 +434,7 @@ "type": "query" }, { - "current": { - "selected": false, - "text": "All", - "value": "$__all" - }, + "current": {}, "datasource": { "type": "vertamedia-clickhouse-datasource", "uid": "vertamedia-clickhouse-datasource" @@ -473,6 +462,6 @@ "timezone": "", "title": "Azure", "uid": "dd66838a-ffda-4de2-944f-1828d1671fc9", - "version": 2, + "version": 1, "weekStart": "" } \ No newline at end of file diff --git a/grafana/bitBucket-dashboard.json b/grafana/bitBucket-dashboard.json index 172b9d0b..389c001c 100644 --- a/grafana/bitBucket-dashboard.json +++ b/grafana/bitBucket-dashboard.json @@ -15,7 +15,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 13, + "id": 34, "links": [], "liveNow": false, "panels": [ @@ -44,7 +44,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -103,7 +103,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -162,7 +162,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -212,8 +212,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -283,8 +282,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -472,6 +470,6 @@ "timezone": "", "title": "BitBucket", "uid": "a7772dd5-76c7-48f3-8462-b39fbc20941c", - "version": 2, + "version": 1, "weekStart": "" } \ No newline at end of file diff --git a/grafana/giTea-dashboard.json b/grafana/giTea-dashboard.json index 5f21b3c7..da0e63a2 100644 --- a/grafana/giTea-dashboard.json +++ b/grafana/giTea-dashboard.json @@ -15,7 +15,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 11, + "id": 35, "links": [], "liveNow": false, "panels": [ @@ -44,7 +44,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -103,7 +103,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -162,7 +162,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -212,8 +212,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -283,8 +282,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -361,8 +359,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" } ] } @@ -473,6 +470,6 @@ "timezone": "", "title": "GiTea", "uid": "a1c6d705-91b0-4718-99b2-d93b0221bca9", - "version": 2, + "version": 1, "weekStart": "" } \ No newline at end of file diff --git a/grafana/gitHub-dashboard.json b/grafana/gitHub-dashboard.json index 71420e64..8b3930db 100644 --- a/grafana/gitHub-dashboard.json +++ b/grafana/gitHub-dashboard.json @@ -15,7 +15,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 10, + "id": 37, "links": [], "liveNow": false, "panels": [ @@ -44,7 +44,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}", "google": { "callback": "gmapReady", "key": "" @@ -104,7 +104,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;\n\n", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -163,7 +163,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -396,8 +396,8 @@ { "current": { "selected": false, - "text": "All", - "value": "$__all" + "text": "", + "value": "" }, "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -418,9 +418,13 @@ }, { "current": { - "selected": false, - "text": "All", - "value": "$__all" + "selected": true, + "text": [ + "push" + ], + "value": [ + "push" + ] }, "datasource": { "type": "vertamedia-clickhouse-datasource", diff --git a/grafana/gitLab-dashboard.json b/grafana/gitLab-dashboard.json index feb82973..00c49d0b 100644 --- a/grafana/gitLab-dashboard.json +++ b/grafana/gitLab-dashboard.json @@ -15,7 +15,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 14, + "id": 36, "links": [], "liveNow": false, "panels": [ @@ -44,7 +44,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'force',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [10, 10], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}\n", + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const eventTypes = data.series[0].fields[0].values;\n const authors = data.series[0].fields[1].values;\n const repoNames = data.series[0].fields[2].values;\n const total = data.series[0].fields[3].values; // Assuming you have a field named \"Total\"\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n authors.forEach((author, index) => {\n const sourceNode = {\n name: author,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const eventTypeNode = {\n name: eventTypes[index],\n category: 1, // Category for eventType nodes\n symbolSize: 40, // Size for eventType nodes\n };\n\n const repoNode = {\n name: repoNames[index],\n category: 2, // Category for repo nodes\n symbolSize: 30, // Size for repo nodes\n };\n\n const totalNode = {\n name: `Total: ${total[index]}`, // Assuming you have an array \"total\"\n category: 3, // Category for total nodes\n symbolSize: 20, // Size for total nodes\n };\n\n // Ensure source, eventType, repo, and total nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === eventTypeNode.name)) {\n nodes.push(eventTypeNode);\n }\n\n if (!nodes.some((node) => node.name === repoNode.name)) {\n nodes.push(repoNode);\n }\n\n if (!nodes.some((node) => node.name === totalNode.name)) {\n nodes.push(totalNode);\n }\n\n // Create links between author, eventType, repo, and total nodes\n links.push({\n source: author,\n target: eventTypes[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: repoNames[index],\n });\n\n links.push({\n source: eventTypes[index],\n target: totalNode.name,\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Authors',\n },\n {\n name: 'Event Type',\n },\n {\n name: 'Repo Names',\n },\n {\n name: 'Total', // Add a category for \"Total\" nodes\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Authors', 'Event Types', 'Repo Names', 'Total'], // Add \"Total\" to legend data\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: { // Add textStyle property to configure text style\n color: '#000', // Set the text color to a brighter color, such as white (#FFF)\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n\n // Increase the size of arrow marks\n edgeSymbolSize: [12, 12], // Set the arrow size here\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Display a custom message when data is not available\n const option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n\n return option;\n}", "google": { "callback": "gmapReady", "key": "" @@ -103,7 +103,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Push_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%', // Adjust the left margin to position it on the top left\n top: '5%', // Adjust the top margin to position it on the top left\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n name: 'Push_Events',\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let options; // Initialize the options variable\n\nif (!data || !data.series || data.series.length === 0 || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n options = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract Author and Push_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const pushEvents = data.series[0].fields.find((f) => f.name === 'Push_Events').values;\n\n // Create the ECharts options\n options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Push_Events'],\n orient: 'vertical', // Change the orientation to vertical\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: pushEvents,\n type: 'line',\n areaStyle: {\n color: 'rgba(0, 128, 255, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'blue', // Set the line color\n },\n name: 'Push_Events',\n },\n ],\n };\n}\n\nreturn options;\n", "google": { "callback": "gmapReady", "key": "" @@ -162,7 +162,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract Author and Merge_Events data from the series\nconst categories = data.series[0].fields.find((f) => f.name === 'Author').values;\nconst mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n// Create the ECharts options\nconst options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n};\n\nreturn options;\n", + "getOption": "let option; // Initialize the option variable\n\n// Define a default options object\nconst defaultOptions = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n};\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = defaultOptions;\n} else {\n // Extract Author and Merge_Events data from the series\n const categories = data.series[0].fields.find((f) => f.name === 'Author').values;\n const mergeEvents = data.series[0].fields.find((f) => f.name === 'Merge_Events').values;\n\n // Create the ECharts options\n const options = {\n grid: {\n bottom: '3%',\n containLabel: true,\n left: '3%',\n right: '4%',\n top: '4%',\n },\n toolbox: {\n right: '5%', // Adjust the right margin to position it on the top right\n top: '0%', // Adjust the top margin to position it on the top right\n feature: {\n dataZoom: {\n yAxisIndex: 'none',\n },\n restore: {},\n },\n },\n tooltip: {\n trigger: 'axis',\n axisPointer: {\n type: 'shadow',\n },\n },\n xAxis: {\n type: 'category',\n data: categories,\n },\n yAxis: {\n type: 'value',\n },\n legend: {\n data: ['Merge_Events'],\n orient: 'vertical',\n left: '5%',\n top: '5%',\n },\n series: [\n {\n data: mergeEvents,\n type: 'line',\n name: 'Merge_Events',\n areaStyle: {\n color: 'rgba(255, 0, 0, 0.3)', // Set the area (shadow) color\n },\n lineStyle: {\n color: 'red', // Set the line color\n },\n },\n ],\n };\n\n option = options; // Assign the options to the outer variable\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -212,8 +212,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -283,8 +282,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -422,13 +420,9 @@ "list": [ { "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "selected": false, + "text": "All", + "value": "$__all" }, "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -449,13 +443,9 @@ }, { "current": { - "selected": true, - "text": [ - "All" - ], - "value": [ - "$__all" - ] + "selected": false, + "text": "All", + "value": "$__all" }, "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -484,6 +474,6 @@ "timezone": "", "title": "GitLab", "uid": "ec8b9cb1-f9ae-4139-b270-4824b6508eff", - "version": 2, + "version": 1, "weekStart": "" } \ No newline at end of file diff --git a/grafana/kubeData-dashboard.json b/grafana/kubeData-dashboard.json index ce8dfaf6..e253f234 100644 --- a/grafana/kubeData-dashboard.json +++ b/grafana/kubeData-dashboard.json @@ -21,7 +21,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 9, + "id": 31, "links": [], "liveNow": false, "panels": [ @@ -31,11 +31,247 @@ "uid": "vertamedia-clickhouse-datasource" }, "gridPos": { - "h": 11, + "h": 14, "w": 24, "x": 0, "y": 0 }, + "id": 6, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND ClusterName IN ($clusterName) AND Kind IN ('Pod', 'Node', 'Deployment')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "rawQuery": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE EventTime >= toDateTime(1698927439) AND EventTime <= toDateTime(1698927739) AND ClusterName IN ('beta-cluster') AND Kind IN ('Pod', 'Node', 'Deployment')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "K8s metrics status", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 8, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND ClusterName IN ($clusterName) AND Kind IN ('Service')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "rawQuery": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE EventTime >= toDateTime(1698931712) AND EventTime <= toDateTime(1698932012) AND ClusterName IN ('beta-cluster') AND Kind IN ('Service')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Service Events by Cluster and Reason", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 9, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Define the data from your JSON\n const clusterNames = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const counts = data.series[0].fields[3].values;\n\n // Create the Sankey chart configuration\n option = {\n series: {\n type: 'sankey',\n layout: 'none',\n emphasis: {\n focus: 'adjacency',\n },\n data: [],\n links: [],\n },\n tooltip: {\n trigger: 'item',\n formatter: (params) => {\n if (params.dataType === 'node') {\n return params.name;\n }\n if (params.dataType === 'edge') {\n return `Count: ${counts[params.dataIndex]}`; // Display count values\n }\n return '';\n },\n },\n };\n\n // Create nodes for ClusterName, Kind, and Reason\n const uniqueClusterNames = Array.from(new Set(clusterNames));\n const uniqueKinds = Array.from(new Set(kinds));\n const uniqueReasons = Array.from(new Set(reasons));\n\n uniqueClusterNames.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueKinds.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n uniqueReasons.forEach((name, index) => {\n option.series.data.push({\n name: name,\n });\n });\n\n\n // Create links from Kind to Reason\n kinds.forEach((kind, index) => {\n const sourceIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kind);\n const targetIndex = 1 * uniqueClusterNames.length + uniqueKinds.length + uniqueReasons.indexOf(reasons[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: counts[index], // Use count values\n });\n });\n\n // Create links from ClusterName to Kind\n clusterNames.forEach((clusterName, index) => {\n const sourceIndex = uniqueClusterNames.indexOf(clusterName);\n const targetIndex = uniqueClusterNames.length + uniqueKinds.indexOf(kinds[index]);\n option.series.links.push({\n source: sourceIndex,\n target: targetIndex,\n value: 1,\n });\n });\n}\n\n\nreturn option;\n// Render the chart\nmyChart.setOption(option);\n\n", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND Kind IN ('PersistentVolume','PersistentVolumeClaim')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC\n", + "rawQuery": "SELECT ClusterName, Kind, Reason, COUNT(*) as Count\nFROM default.events\nWHERE EventTime >= toDateTime(1698931738) AND EventTime <= toDateTime(1698932038) AND Kind IN ('PersistentVolume','PersistentVolumeClaim')\nGROUP BY ClusterName, Kind, Reason\nORDER BY Count DESC", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "PV, PVC events by cluster and reason", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 7, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n\n // Extract data from your JSON\n const clusters = data.series[0].fields[0].values;\n const hosts = data.series[0].fields[1].values;\n const reasons = data.series[0].fields[2].values;\n const eventTimes = data.series[0].fields[3].values;\n\n // Create a hierarchical structure for the tree chart starting with ClusterName\n const hierarchy = {\n name: 'Cluster Hierarchy',\n children: [],\n };\n\n for (let i = 0; i < clusters.length; i++) {\n const cluster = clusters[i];\n const host = hosts[i];\n const reason = reasons[i];\n const eventTime = eventTimes[i];\n\n // Find or create the cluster node\n let clusterNode = hierarchy.children.find((node) => node.name === cluster);\n if (!clusterNode) {\n clusterNode = { name: cluster, children: [] };\n hierarchy.children.push(clusterNode);\n }\n\n // Find or create the host node under the cluster\n let hostNode = clusterNode.children.find((node) => node.name === host);\n if (!hostNode) {\n hostNode = { name: host, children: [] };\n clusterNode.children.push(hostNode);\n }\n\n // Find or create the reason node under the host\n let reasonNode = hostNode.children.find((node) => node.name === reason);\n if (!reasonNode) {\n reasonNode = { name: reason, children: [] };\n hostNode.children.push(reasonNode);\n }\n\n // Create the eventTime node under the reason\n reasonNode.children.push({ name: eventTime });\n }\n\n // Create the tree chart using ECharts\n const option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Start directly from the Cluster Hierarchy node\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%', // Adjust the right margin to provide more space for labels\n symbolSize: 7,\n label: {\n position: 'inside', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'center', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n leaves: {\n label: {\n position: 'right', // Position labels inside the node\n verticalAlign: 'middle',\n align: 'left', // Center-align labels\n fontSize: 15,\n fontWeight: 'bold',\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\nreturn option;", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Host, Reason, EventTime\nFROM default.events\nWHERE $timeFilterByColumn(EventTime) AND ClusterName IN ($clusterName) AND Kind = 'Node' AND Kind != ' '\nGROUP BY ClusterName, Host, Reason, EventTime", + "rawQuery": "SELECT ClusterName, Host, Reason, EventTime\nFROM default.events\nWHERE EventTime >= toDateTime(1698927382) AND EventTime <= toDateTime(1698927682) AND ClusterName IN ('beta-cluster') AND Kind = 'Node' AND Kind != ' '\nGROUP BY ClusterName, Host, Reason, EventTime", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Node Events by Cluster, Host, Reason, and EventTime", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 35 + }, "id": 5, "options": { "baidu": { @@ -50,7 +286,7 @@ "key": "", "plugin": "AMap.Scale,AMap.ToolBar" }, - "getOption": "// Extract data from your JSON\nconst clusterNames = data.series[0].fields[0].values; // New column for ClusterName\nconst namespaces = data.series[0].fields[1].values;\nconst kinds = data.series[0].fields[2].values; // Adjusted index for Kind\nconst counts = data.series[0].fields[3].values; // New column for Count\n\n// Create a hierarchical structure from the data without a root node\nconst hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n};\n\nconst seenClusterNames = new Set();\nconst seenNamespaces = new Set();\n\nfor (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n}\n\n// Create the tree chart using ECharts\nconst option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n};\nreturn option;", + "getOption": "let option; // Initialize the option variable\n\nif (typeof data === 'undefined' || !data.series || !data.series[0] || !data.series[0].fields) {\n // Data is not available or doesn't have the expected structure\n option = {\n title: {\n text: 'Data not available',\n textStyle: {\n fontSize: 24,\n fontWeight: 'bold',\n },\n left: 'center',\n top: 'middle',\n },\n };\n} else {\n // Extract data from your JSON as before\n const clusterNames = data.series[0].fields[0].values; // New column for ClusterName\n const namespaces = data.series[0].fields[1].values;\n const kinds = data.series[0].fields[2].values; // Adjusted index for Kind\n const counts = data.series[0].fields[3].values; // New column for Count\n\n // Create a hierarchical structure from the data without a root node\n const hierarchy = {\n name: 'root', // Use 'root' as a placeholder\n children: [],\n };\n\n const seenClusterNames = new Set();\n const seenNamespaces = new Set();\n\n for (let i = 0; i < clusterNames.length; i++) {\n const clusterName = clusterNames[i];\n const namespace = namespaces[i];\n const kind = kinds[i];\n const count = counts[i]; // Get the count value\n\n if (!seenClusterNames.has(clusterName)) {\n seenClusterNames.add(clusterName);\n const clusterNode = { name: clusterName, children: [] };\n hierarchy.children.push(clusterNode);\n seenNamespaces.clear(); // Reset seenNamespaces for each cluster\n }\n\n const clusterNode = hierarchy.children.find((node) => node.name === clusterName);\n\n if (!seenNamespaces.has(namespace)) {\n seenNamespaces.add(namespace);\n const namespaceNode = { name: namespace, children: [] };\n clusterNode.children.push(namespaceNode);\n }\n\n const namespaceNode = clusterNode.children.find((node) => node.name === namespace);\n const kindNode = { name: kind, children: [{ name: `Count: ${count}` }] }; // Include the count as a child node\n namespaceNode.children.push(kindNode);\n }\n\n // Create the tree chart using ECharts\n option = {\n tooltip: {\n trigger: 'item',\n triggerOn: 'mousemove',\n formatter: function (params) {\n const node = params.data;\n let tooltip = '';\n if (node.column) {\n tooltip += `${node.column}: ${node.name}`;\n } else {\n tooltip += node.name;\n }\n return tooltip;\n },\n },\n series: [\n {\n type: 'tree',\n data: hierarchy.children, // Use the children directly\n top: '1%',\n left: '7%',\n bottom: '1%',\n right: '20%',\n symbolSize: 7,\n label: {\n position: 'left',\n verticalAlign: 'middle',\n align: 'right',\n fontSize: 15, // Increase the text size for regular nodes\n fontWeight: 'bold', // Set the font weight to bold\n },\n leaves: {\n label: {\n position: 'right',\n verticalAlign: 'middle',\n align: 'left',\n fontSize: 15, // Increase the text size for leaves\n fontWeight: 'bold', // Set the font weight to bold\n },\n },\n emphasis: {\n focus: 'descendant',\n },\n expandAndCollapse: true,\n animationDuration: 550,\n animationDurationUpdate: 750,\n },\n ],\n };\n}\n\nreturn option;\n", "google": { "callback": "gmapReady", "key": "" @@ -101,8 +337,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -117,7 +352,7 @@ "h": 7, "w": 24, "x": 0, - "y": 11 + "y": 46 }, "id": 4, "options": { @@ -180,8 +415,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -196,7 +430,7 @@ "h": 16, "w": 24, "x": 0, - "y": 18 + "y": 53 }, "id": 2, "options": { @@ -342,6 +576,6 @@ "timezone": "", "title": "Kubedata", "uid": "Qq-FK1rVz", - "version": 2, + "version": 1, "weekStart": "" } \ No newline at end of file diff --git a/grafana/kubvizDsahboard.json b/grafana/kubvizDsahboard.json index e4968f20..374d131b 100644 --- a/grafana/kubvizDsahboard.json +++ b/grafana/kubvizDsahboard.json @@ -21,7 +21,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 126, + "id": 32, "links": [], "liveNow": false, "panels": [ @@ -173,6 +173,381 @@ "title": "Clusters with Most Activity", "type": "gauge" }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "gridPos": { + "h": 9, + "w": 13, + "x": 0, + "y": 6 + }, + "id": 72, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "// Check if data.series exists\nif (data.series && data.series.length > 0) {\n const reasons = data.series[0].fields[0].values;\n const kinds = data.series[0].fields[1].values;\n const eventTimes = data.series[0].fields[2].values;\n\n // Create nodes and links\n const nodes = [];\n const links = [];\n\n reasons.forEach((reason, index) => {\n const sourceNode = {\n name: reason,\n category: 0, // Category for source nodes\n symbolSize: 60, // Size for source nodes\n };\n\n const kindNode = {\n name: kinds[index],\n category: 1, // Category for kind nodes\n symbolSize: 40, // Size for kind nodes\n };\n\n const eventTimeNode = {\n name: eventTimes[index],\n category: 2, // Category for eventTime nodes\n symbolSize: 20, // Size for eventTime nodes\n };\n\n // Ensure source, kind, and eventTime nodes are unique before adding them\n if (!nodes.some((node) => node.name === sourceNode.name)) {\n nodes.push(sourceNode);\n }\n\n if (!nodes.some((node) => node.name === kindNode.name)) {\n nodes.push(kindNode);\n }\n\n if (!nodes.some((node) => node.name === eventTimeNode.name)) {\n nodes.push(eventTimeNode);\n }\n\n // Create links between reason, kind, and eventTime nodes\n links.push({\n source: reason,\n target: kinds[index],\n });\n\n links.push({\n source: kinds[index],\n target: eventTimes[index],\n });\n });\n\n // Create categories for nodes\n const categories = [\n {\n name: 'Reasons',\n },\n {\n name: 'Nodes',\n },\n {\n name: 'Event Times',\n },\n ];\n\n // Create ECharts option\n const option = {\n tooltip: {\n trigger: 'item',\n formatter: '{b}',\n },\n legend: {\n x: 'left',\n data: ['Reasons', 'Nodes', 'Event Times'],\n },\n series: [\n {\n type: 'graph',\n layout: 'circular',\n roam: true,\n label: {\n show: true,\n textStyle: {\n color: '#000',\n },\n },\n force: {\n repulsion: 100,\n gravity: 0.1,\n edgeLength: 150,\n },\n data: nodes,\n links: links,\n draggable: true,\n categories: categories,\n edgeSymbol: [\"none\", \"arrow\"],\n edgeSymbolSize: [12, 12],\n lineStyle: {\n color: \"#000000\",\n curveness: 0,\n opacity: 0.3,\n },\n },\n ],\n };\n\n // Return the ECharts option\n return option;\n} else {\n // Handle the case when data.series does not exist\n return {};\n}", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT Reason, Host, EventTime\nFROM default.events\nWHERE Kind IN ('Node') AND Reason IN ('NodeNotReady')", + "rawQuery": "SELECT Reason, Host, EventTime\nFROM default.events\nWHERE Kind IN ('Node') AND Reason IN ('NodeNotReady')", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "NodeNotReady Events for Nodes", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "gridPos": { + "h": 9, + "w": 11, + "x": 13, + "y": 6 + }, + "id": 70, + "options": { + "baidu": { + "callback": "bmapReady", + "key": "" + }, + "editor": { + "format": "auto", + "height": 600 + }, + "gaode": { + "key": "", + "plugin": "AMap.Scale,AMap.ToolBar" + }, + "getOption": "let kind = [];\nlet resources = [];\n\ndata.series.map((s) => {\n kind = s.fields.find((f) => f.name === 'Kind').values;\n resources = s.fields.find((f) => f.name === 'Resources').values;\n});\n\n// Create an empty array to store doughnut chart data\nconst doughnutChartData = [];\n\n// Define colors for doughnut slices\nconst doughnutSliceColors = ['#235894', '#FFFF00', '#FF0000', '#00FF00', '#FFA500'];\n\n// Map severity and counts to doughnut chart data\nkind.forEach((kinddata, index) => {\n doughnutChartData.push({\n value: resources[index],\n name: kinddata,\n itemStyle: {\n borderRadius: [10, 10, 10, 10], // Add rounded corners\n color: doughnutSliceColors[index % doughnutSliceColors.length],\n borderWidth: 2,\n borderColor: '#fff',\n },\n });\n});\n\nreturn {\n backgroundColor: '#FFFFFF', // Set the background color to white\n tooltip: {\n trigger: 'item',\n },\n legend: {\n top: '5%',\n left: 'center',\n },\n series: [\n {\n name: 'Access From',\n type: 'pie',\n radius: ['40%', '70%'],\n avoidLabelOverlap: false,\n label: {\n show: false,\n position: 'center',\n },\n emphasis: {\n label: {\n show: true,\n fontSize: 40,\n fontWeight: 'bold',\n },\n },\n labelLine: {\n show: false,\n },\n data: doughnutChartData, // Use the modified doughnut chart data\n },\n ],\n};", + "google": { + "callback": "gmapReady", + "key": "" + }, + "map": "none", + "renderer": "canvas", + "themeEditor": { + "config": "{}", + "height": 400, + "name": "default" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Kind, count(Resource) AS Resources\nFROM default.getall_resources\nWHERE $timeFilterByColumn(EventTime) AND Kind In ('Deployment','Job','Secret', 'ConfigMap', 'Service')\nGROUP BY ClusterName, Kind", + "rawQuery": "SELECT ClusterName, Kind, count(Resource) AS Resources\nFROM default.getall_resources\nWHERE EventTime >= toDateTime(1698841487) AND EventTime <= toDateTime(1698927887) AND Kind In ('Deployment','Job','Secret', 'ConfigMap', 'Service')\nGROUP BY ClusterName, Kind", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Resource Distribution", + "type": "volkovlabs-echarts-panel" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 30, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 15 + }, + "id": 69, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": " SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'Created'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'Created'\n GROUP BY EventTime, Kind, Reason", + "refId": "A", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": " SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'BackOff'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'BackOff'\n GROUP BY EventTime, Kind, Reason", + "refId": "B", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'NodeNotReady'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'NodeNotReady'\n GROUP BY EventTime, Kind, Reason", + "refId": "C", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": " SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'Scheduled'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'Scheduled'\n GROUP BY EventTime, Kind, Reason", + "refId": "D", + "round": "0s", + "skip_comments": true + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "time_series", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "hide": false, + "intervalFactor": 1, + "query": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE $timeFilterByColumn(EventTime) AND Kind = 'Pod' AND Reason = 'FailedScheduling'\n GROUP BY EventTime, Kind, Reason", + "rawQuery": "SELECT EventTime, Kind, Reason, count(*) as total_count\n FROM default.events\n WHERE EventTime >= toDateTime(1698839664) AND EventTime <= toDateTime(1698926064) AND Kind = 'Pod' AND Reason = 'FailedScheduling'\n GROUP BY EventTime, Kind, Reason", + "refId": "E", + "round": "0s", + "skip_comments": true + } + ], + "title": "Pod Events by Reason Over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "center", + "cellOptions": { + "type": "color-text" + }, + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Age" + }, + "properties": [ + { + "id": "custom.cellOptions", + "value": { + "mode": "lcd", + "type": "gauge" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 15 + }, + "id": 71, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "10.0.3", + "targets": [ + { + "datasource": { + "type": "vertamedia-clickhouse-datasource", + "uid": "vertamedia-clickhouse-datasource" + }, + "dateTimeType": "DATETIME", + "extrapolate": true, + "format": "table", + "formattedQuery": "SELECT $timeSeries as t, count() FROM $table WHERE $timeFilter GROUP BY t ORDER BY t", + "intervalFactor": 1, + "query": "SELECT ClusterName, Resource, Age\nFROM default.getall_resources\nWHERE $timeFilterByColumn(EventTime)", + "rawQuery": "SELECT ClusterName, Resource, Age\nFROM default.getall_resources\nWHERE EventTime >= toDateTime(1696336208) AND EventTime <= toDateTime(1698928208)", + "refId": "A", + "round": "0s", + "skip_comments": true + } + ], + "title": "Resource Details by Cluster and Age", + "type": "table" + }, { "datasource": { "type": "vertamedia-clickhouse-datasource", @@ -206,7 +581,7 @@ "h": 4, "w": 5, "x": 0, - "y": 6 + "y": 22 }, "id": 18, "options": { @@ -276,7 +651,7 @@ "h": 4, "w": 5, "x": 5, - "y": 6 + "y": 22 }, "id": 20, "options": { @@ -346,7 +721,7 @@ "h": 4, "w": 5, "x": 10, - "y": 6 + "y": 22 }, "id": 22, "options": { @@ -416,7 +791,7 @@ "h": 4, "w": 5, "x": 15, - "y": 6 + "y": 22 }, "id": 24, "options": { @@ -486,7 +861,7 @@ "h": 4, "w": 4, "x": 20, - "y": 6 + "y": 22 }, "id": 26, "options": { @@ -589,7 +964,7 @@ "h": 6, "w": 13, "x": 0, - "y": 10 + "y": 26 }, "id": 53, "options": { @@ -690,7 +1065,7 @@ "h": 6, "w": 11, "x": 13, - "y": 10 + "y": 26 }, "id": 65, "options": { @@ -746,8 +1121,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -762,7 +1136,7 @@ "h": 4, "w": 6, "x": 0, - "y": 16 + "y": 32 }, "id": 57, "options": { @@ -815,8 +1189,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -835,7 +1208,7 @@ "h": 4, "w": 6, "x": 6, - "y": 16 + "y": 32 }, "id": 63, "options": { @@ -886,8 +1259,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -906,7 +1278,7 @@ "h": 4, "w": 6, "x": 12, - "y": 16 + "y": 32 }, "id": 61, "options": { @@ -957,8 +1329,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -977,7 +1348,7 @@ "h": 4, "w": 6, "x": 18, - "y": 16 + "y": 32 }, "id": 62, "options": { @@ -1032,8 +1403,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1048,7 +1418,7 @@ "h": 4, "w": 6, "x": 0, - "y": 20 + "y": 36 }, "id": 56, "options": { @@ -1101,8 +1471,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1121,7 +1490,7 @@ "h": 4, "w": 6, "x": 6, - "y": 20 + "y": 36 }, "id": 58, "options": { @@ -1172,8 +1541,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1192,7 +1560,7 @@ "h": 4, "w": 6, "x": 12, - "y": 20 + "y": 36 }, "id": 59, "options": { @@ -1243,8 +1611,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1263,7 +1630,7 @@ "h": 4, "w": 6, "x": 18, - "y": 20 + "y": 36 }, "id": 60, "options": { @@ -1325,8 +1692,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "light-yellow", @@ -1370,7 +1736,7 @@ "h": 8, "w": 24, "x": 0, - "y": 24 + "y": 40 }, "id": 44, "options": { @@ -1424,8 +1790,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1444,7 +1809,7 @@ "h": 5, "w": 8, "x": 0, - "y": 32 + "y": 48 }, "id": 66, "options": { @@ -1494,8 +1859,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1514,7 +1878,7 @@ "h": 5, "w": 8, "x": 8, - "y": 32 + "y": 48 }, "id": 68, "options": { @@ -1564,8 +1928,7 @@ "mode": "percentage", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "orange", @@ -1584,7 +1947,7 @@ "h": 5, "w": 8, "x": 16, - "y": 32 + "y": 48 }, "id": 67, "options": { @@ -1646,8 +2009,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1679,7 +2041,7 @@ "h": 8, "w": 24, "x": 0, - "y": 37 + "y": 53 }, "id": 64, "options": { @@ -1755,8 +2117,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1771,7 +2132,7 @@ "h": 9, "w": 12, "x": 0, - "y": 45 + "y": 61 }, "id": 34, "options": { @@ -1855,8 +2216,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1871,7 +2231,7 @@ "h": 9, "w": 12, "x": 12, - "y": 45 + "y": 61 }, "id": 36, "options": { @@ -1955,8 +2315,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1971,7 +2330,7 @@ "h": 8, "w": 8, "x": 0, - "y": 54 + "y": 70 }, "id": 28, "options": { @@ -2054,8 +2413,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2070,7 +2428,7 @@ "h": 8, "w": 8, "x": 8, - "y": 54 + "y": 70 }, "id": 32, "options": { @@ -2154,8 +2512,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2170,7 +2527,7 @@ "h": 8, "w": 8, "x": 16, - "y": 54 + "y": 70 }, "id": 30, "options": { @@ -2240,8 +2597,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "light-yellow", @@ -2277,7 +2633,7 @@ "h": 7, "w": 24, "x": 0, - "y": 62 + "y": 78 }, "id": 42, "options": { @@ -2324,7 +2680,7 @@ "h": 1, "w": 24, "x": 0, - "y": 69 + "y": 85 }, "id": 16, "panels": [ @@ -2352,8 +2708,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -2368,7 +2723,7 @@ "h": 16, "w": 24, "x": 0, - "y": 70 + "y": 110 }, "id": 14, "options": { @@ -2429,7 +2784,7 @@ "h": 1, "w": 24, "x": 0, - "y": 70 + "y": 86 }, "id": 12, "panels": [ @@ -2471,7 +2826,7 @@ "h": 16, "w": 24, "x": 0, - "y": 87 + "y": 127 }, "id": 10, "options": { @@ -2532,7 +2887,7 @@ "h": 1, "w": 24, "x": 0, - "y": 71 + "y": 87 }, "id": 8, "panels": [ @@ -2575,7 +2930,7 @@ "h": 11, "w": 24, "x": 0, - "y": 72 + "y": 112 }, "id": 6, "options": { @@ -2636,7 +2991,7 @@ "h": 1, "w": 24, "x": 0, - "y": 72 + "y": 88 }, "id": 4, "panels": [ @@ -2679,7 +3034,7 @@ "h": 8, "w": 24, "x": 0, - "y": 73 + "y": 113 }, "id": 2, "options": { @@ -2739,7 +3094,7 @@ "list": [] }, "time": { - "from": "now-5m", + "from": "now-24h", "to": "now" }, "timepicker": {},