import React, { PropTypes } from 'react' import formatBytes from 'pretty-bytes' import formatDate from 'date-fns/format' import parseDate from 'date-fns/parse' import { formatNumber, formatPercent } from './NumberUtils' import { ContinentsIndex, CountriesIndex, getCountriesByContinent } from './CountryUtils' import NumberTextInput from './NumberTextInput' const getSum = (data, countries) => countries.reduce((n, country) => n + (data[country] || 0), 0) const addValues = (a, b) => { for (const p in b) { if (p in a) { a[p] += b[p] } else { a[p] = b[p] } } } class Stats extends React.Component { static propTypes = { serverData: PropTypes.object } static defaultProps = { serverData: window.serverData } state = { minRequests: 5000000 } updateMinRequests = (value) => { this.setState({ minRequests: value }) } render() { const { minRequests } = this.state const stats = this.props.serverData.cloudflareStats const { timeseries, totals } = stats // Summary data const sinceDate = parseDate(totals.since) const untilDate = parseDate(totals.until) const uniqueVisitors = totals.uniques.all const totalRequests = totals.requests.all const cachedRequests = totals.requests.cached const totalBandwidth = totals.bandwidth.all const httpStatus = totals.requests.http_status let errorRequests = 0 for (const status in httpStatus) { if (httpStatus.hasOwnProperty(status) && status >= 500) errorRequests += httpStatus[status] } // By Region const regionRows = [] const requestsByCountry = {} const bandwidthByCountry = {} timeseries.forEach(ts => { addValues(requestsByCountry, ts.requests.country) addValues(bandwidthByCountry, ts.bandwidth.country) }) const byRequestsDescending = (a, b) => requestsByCountry[b] - requestsByCountry[a] const continentData = Object.keys(ContinentsIndex).reduce((memo, continent) => { const countries = getCountriesByContinent(continent) memo[continent] = { countries, requests: getSum(requestsByCountry, countries), bandwidth: getSum(bandwidthByCountry, countries) } return memo }, {}) const topContinents = Object.keys(continentData).sort((a, b) => { return continentData[b].requests - continentData[a].requests }) topContinents.forEach(continent => { const continentName = ContinentsIndex[continent] const { countries, requests, bandwidth } = continentData[continent] if (bandwidth !== 0) { regionRows.push( {continentName} {formatNumber(requests)} ({formatPercent(requests / totalRequests)}%) {formatBytes(bandwidth)} ({formatPercent(bandwidth / totalBandwidth)}%) ) const topCountries = countries.sort(byRequestsDescending) topCountries.forEach(country => { const countryRequests = requestsByCountry[country] const countryBandwidth = bandwidthByCountry[country] if (countryRequests > minRequests) { regionRows.push( {CountriesIndex[country].name} {formatNumber(countryRequests)} ({formatPercent(countryRequests / totalRequests)}%) {formatBytes(countryBandwidth)} ({formatPercent(countryBandwidth / totalBandwidth)}%) ) } }) } }) return (

From {formatDate(sinceDate, 'MMM D')} to {formatDate(untilDate, 'MMM D')}, unpkg served {formatNumber(totalRequests)} requests to {formatNumber(uniqueVisitors)} unique visitors, {formatPercent(cachedRequests / totalRequests, 0)}% of which came from the cache (CDN). Over the same period, {formatPercent(errorRequests / totalRequests, 4)}% of requests resulted in server error (returned an HTTP status ≥ 500).

By Region

{regionRows}
Name Requests (% of total) Bandwidth (% of total)
) } } export default Stats