Optimized visits parser to act over the normalized list of visits

This commit is contained in:
Alejandro Celaya 2020-04-10 14:59:12 +02:00
parent fafe920b7b
commit 52dbeb6201
3 changed files with 41 additions and 37 deletions

View file

@ -87,8 +87,8 @@ const ShortUrlVisits = ({ processStatsFromVisits, normalizeVisits }, OpenMapModa
const showTableControls = !loading && visits.length > 0;
const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]);
const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo(
() => processStatsFromVisits(visits),
[ visits ]
() => processStatsFromVisits(normalizedVisits),
[ normalizedVisits ]
);
const mapLocations = values(citiesForMap);

View file

@ -1,60 +1,52 @@
import { isEmpty, isNil, map } from 'ramda';
import { isNil, map } from 'ramda';
import { browserFromUserAgent, extractDomain, osFromUserAgent } from '../../utils/helpers/visits';
import { hasValue } from '../../utils/utils';
const visitLocationHasProperty = (visitLocation, propertyName) =>
!isNil(visitLocation)
&& !isNil(visitLocation[propertyName])
&& !isEmpty(visitLocation[propertyName]);
const updateOsStatsForVisit = (osStats, { userAgent }) => {
const os = osFromUserAgent(userAgent);
const visitHasProperty = (visit, propertyName) => !isNil(visit) && hasValue(visit[propertyName]);
const updateOsStatsForVisit = (osStats, { os }) => {
osStats[os] = (osStats[os] || 0) + 1;
};
const updateBrowsersStatsForVisit = (browsersStats, { userAgent }) => {
const browser = browserFromUserAgent(userAgent);
const updateBrowsersStatsForVisit = (browsersStats, { browser }) => {
browsersStats[browser] = (browsersStats[browser] || 0) + 1;
};
const updateReferrersStatsForVisit = (referrersStats, { referer }) => {
const domain = extractDomain(referer);
const updateReferrersStatsForVisit = (referrersStats, { referer: domain }) => {
referrersStats[domain] = (referrersStats[domain] || 0) + 1;
};
const updateLocationsStatsForVisit = (propertyName) => (stats, { visitLocation }) => {
const hasLocationProperty = visitLocationHasProperty(visitLocation, propertyName);
const value = hasLocationProperty ? visitLocation[propertyName] : 'Unknown';
const updateLocationsStatsForVisit = (propertyName) => (stats, visit) => {
const hasLocationProperty = visitHasProperty(visit, propertyName);
const value = hasLocationProperty ? visit[propertyName] : 'Unknown';
stats[value] = (stats[value] || 0) + 1;
};
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('countryName');
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('cityName');
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('country');
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('city');
const updateCitiesForMapForVisit = (citiesForMapStats, { visitLocation }) => {
if (!visitLocationHasProperty(visitLocation, 'cityName')) {
const updateCitiesForMapForVisit = (citiesForMapStats, visit) => {
if (!visitHasProperty(visit, 'city') || visit.city === 'Unknown') {
return;
}
const { cityName, latitude, longitude } = visitLocation;
const currentCity = citiesForMapStats[cityName] || {
cityName,
const { city, latitude, longitude } = visit;
const currentCity = citiesForMapStats[city] || {
cityName: city,
count: 0,
latLong: [ parseFloat(latitude), parseFloat(longitude) ],
};
currentCity.count++;
citiesForMapStats[cityName] = currentCity;
citiesForMapStats[city] = currentCity;
};
export const processStatsFromVisits = (visits) =>
visits.reduce(
export const processStatsFromVisits = (normalizedVisits) =>
normalizedVisits.reduce(
(stats, visit) => {
// We mutate the original object because it has a big side effect when large data sets are processed
// We mutate the original object because it has a big performance impact when large data sets are processed
updateOsStatsForVisit(stats.os, visit);
updateBrowsersStatsForVisit(stats.browsers, visit);
updateReferrersStatsForVisit(stats.referrers, visit);
@ -74,4 +66,6 @@ export const normalizeVisits = map(({ userAgent, date, referer, visitLocation })
referer: extractDomain(referer),
country: (visitLocation && visitLocation.countryName) || 'Unknown',
city: (visitLocation && visitLocation.cityName) || 'Unknown',
latitude: visitLocation && visitLocation.latitude,
longitude: visitLocation && visitLocation.longitude,
}));

View file

@ -8,8 +8,8 @@ describe('VisitsParser', () => {
visitLocation: {
countryName: 'Spain',
cityName: 'Zaragoza',
latitude: '123.45',
longitude: '-543.21',
latitude: 123.45,
longitude: -543.21,
},
},
{
@ -18,8 +18,8 @@ describe('VisitsParser', () => {
visitLocation: {
countryName: 'United States',
cityName: 'New York',
latitude: '1029',
longitude: '6758',
latitude: 1029,
longitude: 6758,
},
},
{
@ -34,8 +34,8 @@ describe('VisitsParser', () => {
visitLocation: {
countryName: 'Spain',
cityName: 'Zaragoza',
latitude: '123.45',
longitude: '-543.21',
latitude: 123.45,
longitude: -543.21,
},
},
{
@ -47,7 +47,7 @@ describe('VisitsParser', () => {
let stats;
beforeAll(() => {
stats = processStatsFromVisits(visits);
stats = processStatsFromVisits(normalizeVisits(visits));
});
it('properly parses OS stats', () => {
@ -132,6 +132,8 @@ describe('VisitsParser', () => {
country: 'Spain',
city: 'Zaragoza',
date: undefined,
latitude: 123.45,
longitude: -543.21,
},
{
browser: 'Firefox',
@ -140,6 +142,8 @@ describe('VisitsParser', () => {
country: 'United States',
city: 'New York',
date: undefined,
latitude: 1029,
longitude: 6758,
},
{
browser: 'Chrome',
@ -148,6 +152,8 @@ describe('VisitsParser', () => {
country: 'Spain',
city: 'Unknown',
date: undefined,
latitude: undefined,
longitude: undefined,
},
{
browser: 'Chrome',
@ -156,6 +162,8 @@ describe('VisitsParser', () => {
country: 'Spain',
city: 'Zaragoza',
date: undefined,
latitude: 123.45,
longitude: -543.21,
},
{
browser: 'Opera',
@ -164,6 +172,8 @@ describe('VisitsParser', () => {
country: 'Unknown',
city: 'Unknown',
date: undefined,
latitude: undefined,
longitude: undefined,
},
]);
});