User Agent Stats

This commit is contained in:
Qstick
2021-02-20 00:47:49 -05:00
parent 2f702ba06d
commit 0b45929ccc
10 changed files with 156 additions and 78 deletions

View File

@@ -1,6 +1,7 @@
import Chart from 'chart.js';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import colors from 'Styles/Variables/colors';
class BarChart extends Component {
constructor(props) {
@@ -10,7 +11,7 @@ class BarChart extends Component {
componentDidMount() {
this.myChart = new Chart(this.canvasRef.current, {
type: 'bar',
type: this.props.horizontal ? 'horizontalBar' : 'bar',
options: {
maintainAspectRatio: false
},
@@ -18,7 +19,8 @@ class BarChart extends Component {
labels: this.props.data.map((d) => d.label),
datasets: [{
label: this.props.title,
data: this.props.data.map((d) => d.value)
data: this.props.data.map((d) => d.value),
backgroundColor: colors.chartColors
}]
}
});
@@ -39,11 +41,13 @@ class BarChart extends Component {
BarChart.propTypes = {
data: PropTypes.arrayOf(PropTypes.object).isRequired,
horizontal: PropTypes.bool,
title: PropTypes.string.isRequired
};
BarChart.defaultProps = {
data: [],
horizontal: false,
title: ''
};

View File

@@ -1,6 +1,7 @@
import Chart from 'chart.js';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import colors from 'Styles/Variables/colors';
class DoughnutChart extends Component {
constructor(props) {
@@ -25,7 +26,8 @@ class DoughnutChart extends Component {
labels: this.props.data.map((d) => d.label),
datasets: [{
label: this.props.title,
data: this.props.data.map((d) => d.value)
data: this.props.data.map((d) => d.value),
backgroundColor: colors.chartColors
}]
}
});

View File

@@ -4,6 +4,7 @@ import BarChart from 'Components/Chart/BarChart';
import DoughnutChart from 'Components/Chart/DoughnutChart';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import styles from './Stats.css';
@@ -45,60 +46,106 @@ function getNumberGrabsData(indexerStats) {
return data;
}
function getUserAgentGrabsData(indexerStats) {
const data = indexerStats.map((indexer) => {
return {
label: indexer.userAgent ? indexer.userAgent : 'Other',
value: indexer.numberOfGrabs
};
});
data.sort((a, b) => {
return b.value - a.value;
});
return data;
}
function getUserAgentQueryData(indexerStats) {
const data = indexerStats.map((indexer) => {
return {
label: indexer.userAgent ? indexer.userAgent : 'Other',
value: indexer.numberOfQueries
};
});
data.sort((a, b) => {
return b.value - a.value;
});
return data;
}
function Stats(props) {
const {
items,
item,
isFetching,
isPopulated,
error
} = props;
const isLoaded = !!(!error && isPopulated && items.length);
const isLoaded = !!(!error && isPopulated);
return (
<PageContent>
<PageToolbar />
{
isFetching && !isPopulated &&
<LoadingIndicator />
}
<PageContentBody>
{
isFetching && !isPopulated &&
<LoadingIndicator />
}
{
!isFetching && !!error &&
<div className={styles.errorMessage}>
{getErrorMessage(error, 'Failed to load indexer stats from API')}
</div>
}
{
!isFetching && !!error &&
<div className={styles.errorMessage}>
{getErrorMessage(error, 'Failed to load indexer stats from API')}
</div>
}
{
isLoaded &&
<div>
<div className={styles.fullWidthChart}>
<BarChart
data={getAverageResponseTimeData(items)}
title='Average Response Times (ms)'
/>
{
isLoaded &&
<div>
<div className={styles.fullWidthChart}>
<BarChart
data={getAverageResponseTimeData(item.indexers)}
title='Average Response Times (ms)'
/>
</div>
<div className={styles.halfWidthChart}>
<DoughnutChart
data={getTotalRequestsData(item.indexers)}
title='Total Indexer Queries'
/>
</div>
<div className={styles.halfWidthChart}>
<BarChart
data={getNumberGrabsData(item.indexers)}
title='Total Indexer Grabs'
/>
</div>
<div className={styles.halfWidthChart}>
<BarChart
data={getUserAgentQueryData(item.userAgents)}
title='Total User Agent Queries'
horizontal={true}
/>
</div>
<div className={styles.halfWidthChart}>
<BarChart
data={getUserAgentGrabsData(item.userAgents)}
title='Total User Agent Grabs'
horizontal={true}
/>
</div>
</div>
<div className={styles.halfWidthChart}>
<DoughnutChart
data={getTotalRequestsData(items)}
title='Total Indexer Queries'
/>
</div>
<div className={styles.halfWidthChart}>
<BarChart
data={getNumberGrabsData(items)}
title='Total Indexer Grabs'
/>
</div>
</div>
}
}
</PageContentBody>
</PageContent>
);
}
Stats.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
item: PropTypes.object.isRequired,
isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired,
error: PropTypes.object,

View File

@@ -14,13 +14,13 @@ export const defaultState = {
isFetching: false,
isPopulated: false,
error: null,
items: [],
item: {},
details: {
isFetching: false,
isPopulated: false,
error: null,
items: []
item: []
}
};

View File

@@ -181,5 +181,10 @@ module.exports = {
//
// Table
tableRowHoverBackgroundColor: '#fafbfc'
tableRowHoverBackgroundColor: '#fafbfc',
//
// Charts
chartColors: ['#f4d166', '#f6c760', '#f8bc58', '#f8b252', '#f7a84a', '#f69e41', '#f49538', '#f38b2f', '#f28026', '#f0751e', '#eb6c1c', '#e4641e', '#de5d1f', '#d75521', '#cf4f22', '#c64a22', '#bc4623', '#b24223', '#a83e24', '#9e3a26']
};