From b3fdf1eabefcd15f8ed8be3bb64d14ee20c7883a Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 7 Mar 2020 00:22:56 +0000 Subject: [PATCH] Improve verbose mode logging - Support passing a log message function to `logging.log` for lazy evaluation - Log results (or at least lengths) of all API functions - Log merged config during initialisation - Log distance calculation duration --- src/api.js | 37 ++++++++++++++++++++++++++++++++++--- src/index.d.ts | 3 +++ src/logging.js | 16 +++++++++++++++- src/main.js | 3 +++ src/store/actions.js | 17 ++++++++++++++++- src/util.js | 15 +++++++++++++++ 6 files changed, 86 insertions(+), 5 deletions(-) diff --git a/src/api.js b/src/api.js index 74d35b8..ec433b1 100644 --- a/src/api.js +++ b/src/api.js @@ -1,5 +1,5 @@ import { log, logLevels } from "@/logging"; -import { getApiUrl } from "@/util"; +import { getApiUrl, getLocationHistoryCount } from "@/util"; /** * Fetch an API resource. @@ -24,6 +24,7 @@ export const getVersion = async () => { const response = await fetchApi("/api/0/version"); const json = await response.json(); const version = json.version; + log("API", () => `[getVersion] ${version}`); return version; }; @@ -36,6 +37,7 @@ export const getUsers = async () => { const response = await fetchApi("/api/0/list"); const json = await response.json(); const users = json.results; + log("API", () => `[getUsers] Fetched ${users.length} users`); return users; }; @@ -56,6 +58,15 @@ export const getDevices = async users => { devices[user] = userDevices; }) ); + log("API", () => { + const devicesCount = Object.keys(devices) + .map(user => devices[user].length) + .reduce((a, b) => a + b, 0); + return ( + `[getDevices] Fetched ${devicesCount} ` + + `devices for ${users.length} users` + ); + }); return devices; }; @@ -76,7 +87,12 @@ export const getLastLocations = async (user, device) => { } const response = await fetchApi("/api/0/last", params); const json = await response.json(); - return json; + const lastLocations = json; + log( + "API", + () => `[getLastLocations] Fetched ${lastLocations.length} last locations` + ); + return lastLocations; }; /** @@ -102,7 +118,15 @@ export const getUserDeviceLocationHistory = async ( format: "json", }); const json = await response.json(); - return json.data; + const userDeviceLocationHistory = json.data; + log( + "API", + () => + `[getUserDeviceLocationHistory] Fetched ` + + `${userDeviceLocationHistory.length} locations for ` + + `${user}/${device} from ${start} - ${end}` + ); + return userDeviceLocationHistory; }; /** @@ -131,6 +155,13 @@ export const getLocationHistory = async (devices, start, end) => { ); }) ); + log("API", () => { + const locationHistoryCount = getLocationHistoryCount(locationHistory); + return ( + "[getLocationHistory] Fetched " + + `${locationHistoryCount} locations in total` + ); + }); return locationHistory; }; diff --git a/src/index.d.ts b/src/index.d.ts index 4816dc1..b928d06 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -204,6 +204,9 @@ interface QueryParams { /** Callback for new WebSocket location messages. */ interface WebSocketLocationCallback { (): void } +/** Function for lazy evaluation of log messages. */ +interface LogMessageFunction { (): string } + /** A CSS color. */ type Color = string; diff --git a/src/logging.js b/src/logging.js index af74faa..dc47299 100644 --- a/src/logging.js +++ b/src/logging.js @@ -20,6 +20,16 @@ const logColors = { [logLevels.ERROR]: "#ad1515", }; +/** + * Log a message to the browser's console. + * + * Convenience wrapper for `console.{info,warn,error}` doing some formatting + * and taking the `verbose` config option into account. + * + * @param {String} label Log message label, useful for filtering + * @param {String|LogMessageFunction} message Log message + * @param {String} [level] Log level, use `logLevels` constants + */ export const log = (label, message, level = logLevels.INFO) => { if (!Object.keys(logLevels).includes(level)) { log("WARNING", `invalid log level: ${level}`, logLevels.WARNING); @@ -35,5 +45,9 @@ export const log = (label, message, level = logLevels.INFO) => { padding: 3px; `; const logFunc = logFunctions[level]; - logFunc(`%c${label}`, css, message); + logFunc( + `%c${label}`, + css, + typeof message === "function" ? message() : message + ); }; diff --git a/src/main.js b/src/main.js index 0ccbb7a..8e28a97 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,7 @@ import Vue from "vue"; import App from "@/App.vue"; import config from "@/config"; +import { log } from "@/logging"; import i18n from "@/i18n"; import router from "@/router"; import store from "@/store"; @@ -12,6 +13,8 @@ Vue.use(VOutsideEvents); Vue.config.productionTip = false; +log("CONFIG", config); + Vue.prototype.$config = config; new Vue({ diff --git a/src/store/actions.js b/src/store/actions.js index 17d4415..b386617 100644 --- a/src/store/actions.js +++ b/src/store/actions.js @@ -1,7 +1,12 @@ import * as types from "@/store/mutation-types"; import * as api from "@/api"; import config from "@/config"; -import { distanceBetweenCoordinates, isIsoDateTime } from "@/util"; +import { log } from "@/logging"; +import { + distanceBetweenCoordinates, + isIsoDateTime, + getLocationHistoryCount, +} from "@/util"; /** * Populate the state from URL query parameters. @@ -118,6 +123,7 @@ const getLastLocations = async ({ commit, state }) => { }; const _getDistanceTravelled = locationHistory => { + const start = Date.now(); let distanceTravelled = 0; Object.keys(locationHistory).forEach(user => { Object.keys(locationHistory[user]).forEach(device => { @@ -143,6 +149,15 @@ const _getDistanceTravelled = locationHistory => { }); }); }); + const end = Date.now(); + log("DISTANCE", () => { + const locationHistoryCount = getLocationHistoryCount(locationHistory); + const duration = (end - start) / 1000; + return ( + `[_getDistanceTravelled] Took ${duration} seconds to ` + + `calculate distance of ${locationHistoryCount} locations` + ); + }); return distanceTravelled; }; diff --git a/src/util.js b/src/util.js index c1f230d..69dccf8 100644 --- a/src/util.js +++ b/src/util.js @@ -101,3 +101,18 @@ export const humanReadableDistance = distance => { maximumFractionDigits: 1, })} ${unit}`; }; + +/** + * Get the total number of locations from a nested location history. + * + * @param {LocationHistory} locationHistory Location history + * @returns {Number} Total number of locations + */ +export const getLocationHistoryCount = locationHistory => + Object.keys(locationHistory) + .map(user => + Object.keys(locationHistory[user]) + .map(device => locationHistory[user][device].length) + .reduce((a, b) => a + b, 0) + ) + .reduce((a, b) => a + b, 0);