diff --git a/frontend/src/Components/Chart/BarChart.js b/frontend/src/Components/Chart/BarChart.js
index c95e5f2a5..ca225952b 100644
--- a/frontend/src/Components/Chart/BarChart.js
+++ b/frontend/src/Components/Chart/BarChart.js
@@ -1,4 +1,4 @@
-import Chart from 'chart.js';
+import Chart from 'chart.js/auto';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import colors from 'Styles/Variables/colors';
@@ -11,9 +11,19 @@ class BarChart extends Component {
componentDidMount() {
this.myChart = new Chart(this.canvasRef.current, {
- type: this.props.horizontal ? 'horizontalBar' : 'bar',
+ type: 'bar',
options: {
- maintainAspectRatio: false
+ indexAxis: this.props.horizontal ? 'y' : 'x',
+ maintainAspectRatio: false,
+ plugins: {
+ title: {
+ display: true,
+ text: this.props.title
+ },
+ legend: {
+ display: this.props.legend
+ }
+ }
},
data: {
labels: this.props.data.map((d) => d.label),
@@ -42,12 +52,14 @@ class BarChart extends Component {
BarChart.propTypes = {
data: PropTypes.arrayOf(PropTypes.object).isRequired,
horizontal: PropTypes.bool,
+ legend: PropTypes.bool,
title: PropTypes.string.isRequired
};
BarChart.defaultProps = {
data: [],
horizontal: false,
+ legend: false,
title: ''
};
diff --git a/frontend/src/Components/Chart/DoughnutChart.js b/frontend/src/Components/Chart/DoughnutChart.js
index 722ee695a..5f38991c6 100644
--- a/frontend/src/Components/Chart/DoughnutChart.js
+++ b/frontend/src/Components/Chart/DoughnutChart.js
@@ -1,4 +1,4 @@
-import Chart from 'chart.js';
+import Chart from 'chart.js/auto';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import colors from 'Styles/Variables/colors';
diff --git a/frontend/src/Components/Chart/LineChart.js b/frontend/src/Components/Chart/LineChart.js
index 3d7d1ebac..8e61ea5e3 100644
--- a/frontend/src/Components/Chart/LineChart.js
+++ b/frontend/src/Components/Chart/LineChart.js
@@ -1,4 +1,4 @@
-import Chart from 'chart.js';
+import Chart from 'chart.js/auto';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
diff --git a/frontend/src/Components/Chart/StackedBarChart.js b/frontend/src/Components/Chart/StackedBarChart.js
new file mode 100644
index 000000000..dbfc88733
--- /dev/null
+++ b/frontend/src/Components/Chart/StackedBarChart.js
@@ -0,0 +1,67 @@
+import Chart from 'chart.js/auto';
+import PropTypes from 'prop-types';
+import React, { Component } from 'react';
+import colors from 'Styles/Variables/colors';
+
+class StackedBarChart extends Component {
+ constructor(props) {
+ super(props);
+ this.canvasRef = React.createRef();
+ }
+
+ componentDidMount() {
+ this.myChart = new Chart(this.canvasRef.current, {
+ type: 'bar',
+ options: {
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ stacked: true
+ },
+ y: {
+ stacked: true
+ }
+ },
+ plugins: {
+ title: {
+ display: true,
+ text: this.props.title
+ }
+ }
+ },
+ data: {
+ labels: this.props.data.labels,
+ datasets: this.props.data.datasets.map((d, index) => {
+ return {
+ label: d.label,
+ data: d.data,
+ backgroundColor: colors.chartColors[index]
+ };
+ })
+ }
+ });
+ }
+
+ componentDidUpdate() {
+ this.myChart.data.labels = this.props.data.labels;
+ this.myChart.data.datasets = this.props.data.datasets;
+ this.myChart.update();
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+StackedBarChart.propTypes = {
+ data: PropTypes.object.isRequired,
+ title: PropTypes.string.isRequired
+};
+
+StackedBarChart.defaultProps = {
+ title: ''
+};
+
+export default StackedBarChart;
diff --git a/frontend/src/Indexer/Stats/Stats.js b/frontend/src/Indexer/Stats/Stats.js
index 777078e82..c3984f60e 100644
--- a/frontend/src/Indexer/Stats/Stats.js
+++ b/frontend/src/Indexer/Stats/Stats.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import BarChart from 'Components/Chart/BarChart';
-import DoughnutChart from 'Components/Chart/DoughnutChart';
+import StackedBarChart from 'Components/Chart/StackedBarChart';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
@@ -21,12 +21,25 @@ function getAverageResponseTimeData(indexerStats) {
}
function getTotalRequestsData(indexerStats) {
- const data = indexerStats.map((indexer) => {
- return {
- label: indexer.indexerName,
- value: indexer.numberOfQueries
- };
- });
+ const data = {
+ labels: indexerStats.map((indexer) => indexer.indexerName),
+ datasets: [
+ {
+ label: 'Search Queries',
+ data: indexerStats.map((indexer) => indexer.numberOfQueries)
+ },
+ {
+ label: 'Rss Queries',
+ data: indexerStats.map((indexer) => indexer.numberOfRssQueries)
+ },
+ {
+ label: 'Auth Queries',
+ data: indexerStats.map((indexer) => indexer.numberOfAuthQueries)
+ }
+ ]
+ };
+
+ console.log(data);
return data;
}
@@ -112,7 +125,7 @@ function Stats(props) {
/>
-
diff --git a/package.json b/package.json
index 05ff9bbba..062b07b1b 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
"@microsoft/signalr": "5.0.5",
"@sentry/browser": "6.3.1",
"@sentry/integrations": "6.3.1",
- "chart.js": "2.9.4",
+ "chart.js": "3.2.0",
"classnames": "2.3.1",
"clipboard": "2.0.8",
"connected-react-router": "6.9.1",
diff --git a/src/NzbDrone.Core/IndexerStats/IndexerStatistics.cs b/src/NzbDrone.Core/IndexerStats/IndexerStatistics.cs
index 481123e2d..a8b65af07 100644
--- a/src/NzbDrone.Core/IndexerStats/IndexerStatistics.cs
+++ b/src/NzbDrone.Core/IndexerStats/IndexerStatistics.cs
@@ -9,6 +9,8 @@ namespace NzbDrone.Core.IndexerStats
public int AverageResponseTime { get; set; }
public int NumberOfQueries { get; set; }
public int NumberOfGrabs { get; set; }
+ public int NumberOfRssQueries { get; set; }
+ public int NumberOfAuthQueries { get; set; }
}
public class UserAgentStatistics : ResultSet
@@ -16,6 +18,7 @@ namespace NzbDrone.Core.IndexerStats
public string UserAgent { get; set; }
public int NumberOfQueries { get; set; }
public int NumberOfGrabs { get; set; }
+ public int NumberOfRssQueries { get; set; }
}
public class HostStatistics : ResultSet
@@ -23,5 +26,6 @@ namespace NzbDrone.Core.IndexerStats
public string Host { get; set; }
public int NumberOfQueries { get; set; }
public int NumberOfGrabs { get; set; }
+ public int NumberOfRssQueries { get; set; }
}
}
diff --git a/src/NzbDrone.Core/IndexerStats/IndexerStatisticsRepository.cs b/src/NzbDrone.Core/IndexerStats/IndexerStatisticsRepository.cs
index 7bb2b73db..35aa6b658 100644
--- a/src/NzbDrone.Core/IndexerStats/IndexerStatisticsRepository.cs
+++ b/src/NzbDrone.Core/IndexerStats/IndexerStatisticsRepository.cs
@@ -60,6 +60,8 @@ namespace NzbDrone.Core.IndexerStats
.Select(@"Indexers.Id AS IndexerId,
Indexers.Name AS IndexerName,
SUM(CASE WHEN EventType == 2 then 1 else 0 end) AS NumberOfQueries,
+ SUM(CASE WHEN EventType == 3 then 1 else 0 end) AS NumberOfRssQueries,
+ SUM(CASE WHEN EventType == 4 then 1 else 0 end) AS NumberOfAuthQueries,
SUM(CASE WHEN EventType == 1 then 1 else 0 end) AS NumberOfGrabs,
AVG(json_extract(History.Data,'$.elapsedTime')) AS AverageResponseTime")
.Join((t, r) => t.IndexerId == r.Id)
@@ -68,7 +70,8 @@ namespace NzbDrone.Core.IndexerStats
private SqlBuilder UserAgentBuilder() => new SqlBuilder()
.Select(@"json_extract(History.Data,'$.source') AS UserAgent,
SUM(CASE WHEN EventType == 2 then 1 else 0 end) AS NumberOfQueries,
- SUM(CASE WHEN EventType == 1 then 1 else 0 end) AS NumberOfGrabs")
+ SUM(CASE WHEN EventType == 1 then 1 else 0 end) AS NumberOfGrabs,
+ SUM(CASE WHEN EventType == 3 then 1 else 0 end) AS NumberOfRssQueries")
.GroupBy("UserAgent");
}
}
diff --git a/yarn.lock b/yarn.lock
index 8a4441d92..7f1bbac06 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1998,28 +1998,10 @@ character-reference-invalid@^1.0.0:
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560"
integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==
-chart.js@2.9.4:
- version "2.9.4"
- resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684"
- integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==
- dependencies:
- chartjs-color "^2.1.0"
- moment "^2.10.2"
-
-chartjs-color-string@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71"
- integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==
- dependencies:
- color-name "^1.0.0"
-
-chartjs-color@^2.1.0:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0"
- integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==
- dependencies:
- chartjs-color-string "^0.6.0"
- color-convert "^1.9.3"
+chart.js@3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.2.0.tgz#3d0a4b62b6bee428f8547db6aa68c792b130c260"
+ integrity sha512-Ml3R47TvOPW6gQ6T8mg/uPvyOASPpPVVF6xb7ZyHkek1c6kJIT5ScT559afXoDf6uwtpDR2BpCommkA5KT8ODg==
chrome-trace-event@^1.0.2:
version "1.0.3"
@@ -2100,7 +2082,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
-color-convert@^1.3.0, color-convert@^1.9.0, color-convert@^1.9.3:
+color-convert@^1.3.0, color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@@ -4391,7 +4373,7 @@ mobile-detect@1.4.5:
resolved "https://registry.yarnpkg.com/mobile-detect/-/mobile-detect-1.4.5.tgz#da393c3c413ca1a9bcdd9ced653c38281c0fb6ad"
integrity sha512-yc0LhH6tItlvfLBugVUEtgawwFU2sIe+cSdmRJJCTMZ5GEJyLxNyC/NIOAOGk67Fa8GNpOttO3Xz/1bHpXFD/g==
-moment@2.29.1, moment@^2.10.2:
+moment@2.29.1:
version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==