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 showTableControls = !loading && visits.length > 0;
const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]); const normalizedVisits = useMemo(() => normalizeVisits(visits), [ visits ]);
const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo( const { os, browsers, referrers, countries, cities, citiesForMap } = useMemo(
() => processStatsFromVisits(visits), () => processStatsFromVisits(normalizedVisits),
[ visits ] [ normalizedVisits ]
); );
const mapLocations = values(citiesForMap); 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 { browserFromUserAgent, extractDomain, osFromUserAgent } from '../../utils/helpers/visits';
import { hasValue } from '../../utils/utils';
const visitLocationHasProperty = (visitLocation, propertyName) => const visitHasProperty = (visit, propertyName) => !isNil(visit) && hasValue(visit[propertyName]);
!isNil(visitLocation)
&& !isNil(visitLocation[propertyName])
&& !isEmpty(visitLocation[propertyName]);
const updateOsStatsForVisit = (osStats, { userAgent }) => {
const os = osFromUserAgent(userAgent);
const updateOsStatsForVisit = (osStats, { os }) => {
osStats[os] = (osStats[os] || 0) + 1; osStats[os] = (osStats[os] || 0) + 1;
}; };
const updateBrowsersStatsForVisit = (browsersStats, { userAgent }) => { const updateBrowsersStatsForVisit = (browsersStats, { browser }) => {
const browser = browserFromUserAgent(userAgent);
browsersStats[browser] = (browsersStats[browser] || 0) + 1; browsersStats[browser] = (browsersStats[browser] || 0) + 1;
}; };
const updateReferrersStatsForVisit = (referrersStats, { referer }) => { const updateReferrersStatsForVisit = (referrersStats, { referer: domain }) => {
const domain = extractDomain(referer);
referrersStats[domain] = (referrersStats[domain] || 0) + 1; referrersStats[domain] = (referrersStats[domain] || 0) + 1;
}; };
const updateLocationsStatsForVisit = (propertyName) => (stats, { visitLocation }) => { const updateLocationsStatsForVisit = (propertyName) => (stats, visit) => {
const hasLocationProperty = visitLocationHasProperty(visitLocation, propertyName); const hasLocationProperty = visitHasProperty(visit, propertyName);
const value = hasLocationProperty ? visitLocation[propertyName] : 'Unknown'; const value = hasLocationProperty ? visit[propertyName] : 'Unknown';
stats[value] = (stats[value] || 0) + 1; stats[value] = (stats[value] || 0) + 1;
}; };
const updateCountriesStatsForVisit = updateLocationsStatsForVisit('countryName'); const updateCountriesStatsForVisit = updateLocationsStatsForVisit('country');
const updateCitiesStatsForVisit = updateLocationsStatsForVisit('cityName'); const updateCitiesStatsForVisit = updateLocationsStatsForVisit('city');
const updateCitiesForMapForVisit = (citiesForMapStats, { visitLocation }) => { const updateCitiesForMapForVisit = (citiesForMapStats, visit) => {
if (!visitLocationHasProperty(visitLocation, 'cityName')) { if (!visitHasProperty(visit, 'city') || visit.city === 'Unknown') {
return; return;
} }
const { cityName, latitude, longitude } = visitLocation; const { city, latitude, longitude } = visit;
const currentCity = citiesForMapStats[cityName] || { const currentCity = citiesForMapStats[city] || {
cityName, cityName: city,
count: 0, count: 0,
latLong: [ parseFloat(latitude), parseFloat(longitude) ], latLong: [ parseFloat(latitude), parseFloat(longitude) ],
}; };
currentCity.count++; currentCity.count++;
citiesForMapStats[cityName] = currentCity; citiesForMapStats[city] = currentCity;
}; };
export const processStatsFromVisits = (visits) => export const processStatsFromVisits = (normalizedVisits) =>
visits.reduce( normalizedVisits.reduce(
(stats, visit) => { (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); updateOsStatsForVisit(stats.os, visit);
updateBrowsersStatsForVisit(stats.browsers, visit); updateBrowsersStatsForVisit(stats.browsers, visit);
updateReferrersStatsForVisit(stats.referrers, visit); updateReferrersStatsForVisit(stats.referrers, visit);
@@ -74,4 +66,6 @@ export const normalizeVisits = map(({ userAgent, date, referer, visitLocation })
referer: extractDomain(referer), referer: extractDomain(referer),
country: (visitLocation && visitLocation.countryName) || 'Unknown', country: (visitLocation && visitLocation.countryName) || 'Unknown',
city: (visitLocation && visitLocation.cityName) || 'Unknown', city: (visitLocation && visitLocation.cityName) || 'Unknown',
latitude: visitLocation && visitLocation.latitude,
longitude: visitLocation && visitLocation.longitude,
})); }));

View File

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