From d1d786737f6030ef2ee6b3b346697ca7a5dd9c36 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 16 Aug 2024 14:55:00 -0400 Subject: [PATCH 1/6] tidy excessive logs https://github.com/e-mission/e-mission-phone/pull/1165 --- www/js/diary/addressNamesHelper.ts | 3 +-- www/js/diary/timelineHelper.ts | 8 +------- www/js/survey/multilabel/confirmHelper.ts | 3 --- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/www/js/diary/addressNamesHelper.ts b/www/js/diary/addressNamesHelper.ts index de3db47ea..660ab25f4 100644 --- a/www/js/diary/addressNamesHelper.ts +++ b/www/js/diary/addressNamesHelper.ts @@ -111,8 +111,7 @@ async function fetchNominatimLocName(loc_geojson) { const coordsStr = loc_geojson.coordinates.toString(); const cachedResponse = localStorage.getItem(coordsStr); if (cachedResponse) { - logDebug(`fetchNominatimLocName: found cached response for ${coordsStr} = - ${cachedResponse}, skipping fetch`); + logDebug(`fetchNominatimLocName: found cached response for ${coordsStr}`); return; } logDebug('Getting location name for ' + JSON.stringify(coordsStr)); diff --git a/www/js/diary/timelineHelper.ts b/www/js/diary/timelineHelper.ts index d5c1e507b..c1bbf497c 100644 --- a/www/js/diary/timelineHelper.ts +++ b/www/js/diary/timelineHelper.ts @@ -442,10 +442,7 @@ function tripTransitions2UnprocessedTrip( startTs: tripStartTransition.data.ts, endTs: tripEndTransition.data.ts, }; - logDebug(`About to pull location data for range: - ${DateTime.fromSeconds(tripStartTransition.data.ts).toLocaleString(DateTime.DATETIME_MED)} - to - ${DateTime.fromSeconds(tripEndTransition.data.ts).toLocaleString(DateTime.DATETIME_MED)}`); + logDebug(`About to pull location data for range: ${tq.startTs} to ${tq.endTs}`); const getSensorData = window['cordova'].plugins.BEMUserCache.getSensorDataForInterval; return getUnifiedDataForInterval('background/filtered_location', tq, getSensorData).then( (locationList: Array>) => { @@ -605,9 +602,6 @@ export function readUnprocessedTrips( logDebug(`Found ${transitionList.length} transitions. yay!`); const tripsList = transitions2TripTransitions(transitionList); logDebug(`Mapped into ${tripsList.length} trips. yay!`); - tripsList.forEach((trip) => { - logDebug(JSON.stringify(trip, null, 2)); - }); const tripFillPromises = tripsList.map((t) => tripTransitions2UnprocessedTrip(t, appConfig), ); diff --git a/www/js/survey/multilabel/confirmHelper.ts b/www/js/survey/multilabel/confirmHelper.ts index 79695918a..c3a5417dd 100644 --- a/www/js/survey/multilabel/confirmHelper.ts +++ b/www/js/survey/multilabel/confirmHelper.ts @@ -96,12 +96,9 @@ export function labelInputDetailsForTrip(userInputForTrip, appConfigParam?) { Needs REPLACED_MODE`); return getLabelInputDetails(); } else { - logDebug(`Found trip labeled with ${userInputForTrip?.['MODE']?.data?.label}, not labeled with mode of study = ${appConfig.intro.mode_studied}. - Doesn't need REPLACED_MODE`); return baseLabelInputDetails; } } else { - logDebug('No mode of study, so there is no REPLACED_MODE label option'); return getLabelInputDetails(); } } From 791efd305a417c8f7f5b9848425c64b1606df171 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 16 Aug 2024 14:59:38 -0400 Subject: [PATCH 2/6] getUserInputForTimelineEntry: return early if no user inputs to check This is a performance optimization I found while investigating why so many log statements were printed when there were no unprocessed inputs. when userInputList is `[]`, we should return early. --- www/js/survey/inputMatcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/js/survey/inputMatcher.ts b/www/js/survey/inputMatcher.ts index 604c533b2..4a031bec5 100644 --- a/www/js/survey/inputMatcher.ts +++ b/www/js/survey/inputMatcher.ts @@ -168,7 +168,7 @@ export function getUserInputForTimelineEntry( userInputList: UserInputEntry[], ): undefined | UserInputEntry { const logsEnabled = userInputList?.length < 20; - if (userInputList === undefined) { + if (!userInputList?.length) { logDebug('In getUserInputForTimelineEntry, no user input, returning undefined'); return undefined; } From 589e9e778cd898e8e619a289ad59bf8229c421db Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 16 Aug 2024 15:08:50 -0400 Subject: [PATCH 3/6] prevent concurrent retrievals of dynamic config While investigating excessive log statements, I found several repetitive logs for config retrieval. There were several retrievals occuring in parallel because the retrieval is not synchronous but was being requested by multiple parts of the codebase in succession. A better pattern is to cache the promise rather than only caching the result once the promise completes I also updated the return type of getConfig to properly reflect that the promise could resolve as `null`. Throughout the codebase we already account for the possibility of it being null almost everywhere except tests. enketoHelper is the one place I saw that config being null could have been an issue. For tests, we just tell TypeScript to assert non-null with `!` --- www/__tests__/customMetricsHelper.test.ts | 4 ++-- www/__tests__/dynamicConfig.test.ts | 8 ++++---- www/__tests__/enketoHelper.test.ts | 6 +++--- www/__tests__/footprintHelper.test.ts | 8 ++++---- www/__tests__/metHelper.test.ts | 2 +- www/js/config/dynamicConfig.ts | 24 +++++++++++------------ www/js/survey/enketo/enketoHelper.ts | 8 +++----- 7 files changed, 29 insertions(+), 31 deletions(-) diff --git a/www/__tests__/customMetricsHelper.test.ts b/www/__tests__/customMetricsHelper.test.ts index 1c56d7a54..ef840283f 100644 --- a/www/__tests__/customMetricsHelper.test.ts +++ b/www/__tests__/customMetricsHelper.test.ts @@ -37,7 +37,7 @@ it('has no footprint or mets before initialized', () => { it('gets the custom mets', async () => { const appConfig = await getConfig(); - await initCustomDatasetHelper(appConfig); + await initCustomDatasetHelper(appConfig!); //expecting the keys from fakeLabels.json NOT metrics/metDataset.ts expect(getCustomMETs()).toMatchObject({ walk: expect.any(Object), @@ -51,7 +51,7 @@ it('gets the custom mets', async () => { it('gets the custom footprint', async () => { const appConfig = await getConfig(); - await initCustomDatasetHelper(appConfig); + await initCustomDatasetHelper(appConfig!); //numbers from fakeLabels.json expect(getCustomFootprint()).toMatchObject({ walk: 0, diff --git a/www/__tests__/dynamicConfig.test.ts b/www/__tests__/dynamicConfig.test.ts index 12fec433b..a5b1d927d 100644 --- a/www/__tests__/dynamicConfig.test.ts +++ b/www/__tests__/dynamicConfig.test.ts @@ -75,8 +75,8 @@ describe('dynamicConfig', () => { const validToken = `nrelop_${validStudyNrelCommute}_user1`; await initByUser({ token: validToken }); const config = await getConfig(); - expect(config.server.connectUrl).toBe('https://nrel-commute-openpath.nrel.gov/api/'); - expect(config.joined).toEqual({ + expect(config!.server.connectUrl).toBe('https://nrel-commute-openpath.nrel.gov/api/'); + expect(config!.joined).toEqual({ opcode: validToken, study_name: validStudyNrelCommute, subgroup: undefined, @@ -87,8 +87,8 @@ describe('dynamicConfig', () => { const validToken = `nrelop_${validStudyDenverCasr}_test_user1`; await initByUser({ token: validToken }); const config = await getConfig(); - expect(config.server.connectUrl).toBe('https://denver-casr-openpath.nrel.gov/api/'); - expect(config.joined).toEqual({ + expect(config!.server.connectUrl).toBe('https://denver-casr-openpath.nrel.gov/api/'); + expect(config!.joined).toEqual({ opcode: validToken, study_name: validStudyDenverCasr, subgroup: 'test', diff --git a/www/__tests__/enketoHelper.test.ts b/www/__tests__/enketoHelper.test.ts index aedd7deec..5728caf0d 100644 --- a/www/__tests__/enketoHelper.test.ts +++ b/www/__tests__/enketoHelper.test.ts @@ -9,7 +9,7 @@ import { } from '../js/survey/enketo/enketoHelper'; import { mockBEMUserCache } from '../__mocks__/cordovaMocks'; import { mockLogger } from '../__mocks__/globalMocks'; -import { getConfig, _test_resetStoredConfig } from '../../www/js/config/dynamicConfig'; +import { getConfig, _test_resetPromisedConfig } from '../../www/js/config/dynamicConfig'; import fakeConfig from '../__mocks__/fakeConfig.json'; import initializedI18next from '../js/i18nextInit'; @@ -24,7 +24,7 @@ global.URL = require('url').URL; global.Blob = require('node:buffer').Blob; beforeEach(() => { - _test_resetStoredConfig(); + _test_resetPromisedConfig(); }); it('gets the survey config', async () => { @@ -47,7 +47,7 @@ it('gets the survey config', async () => { version: 9, }, }; - expect(config.survey_info.surveys).toMatchObject(mockSurveys); + expect(config!.survey_info.surveys).toMatchObject(mockSurveys); }); it('gets the model response, if avaliable, or returns null', () => { diff --git a/www/__tests__/footprintHelper.test.ts b/www/__tests__/footprintHelper.test.ts index eed592a83..ba49e6645 100644 --- a/www/__tests__/footprintHelper.test.ts +++ b/www/__tests__/footprintHelper.test.ts @@ -50,7 +50,7 @@ const custom_metrics = [ */ it('gets footprint for metrics (custom, fallback 0)', async () => { const appConfig = await getConfig(); - await initCustomDatasetHelper(appConfig); + await initCustomDatasetHelper(appConfig!); expect(getFootprintForMetrics(custom_metrics, 0)).toBe(2.4266); }); @@ -61,14 +61,14 @@ it('gets footprint for metrics (custom, fallback 0)', async () => { */ it('gets footprint for metrics (custom, fallback 0.1)', async () => { const appConfig = await getConfig(); - await initCustomDatasetHelper(appConfig); + await initCustomDatasetHelper(appConfig!); expect(getFootprintForMetrics(custom_metrics, 0.1)).toBe(3.2266); }); //expects TAXI from the fake labels it('gets the highest footprint from the dataset, custom', async () => { const appConfig = await getConfig(); - await initCustomDatasetHelper(appConfig); + await initCustomDatasetHelper(appConfig!); expect(getHighestFootprint()).toBe(0.30741); }); @@ -77,7 +77,7 @@ it('gets the highest footprint from the dataset, custom', async () => { */ it('gets the highest footprint for distance, custom', async () => { const appConfig = await getConfig(); - await initCustomDatasetHelper(appConfig); + await initCustomDatasetHelper(appConfig!); expect(getHighestFootprintForDistance(12345)).toBe(0.30741 * (12345 / 1000)); }); diff --git a/www/__tests__/metHelper.test.ts b/www/__tests__/metHelper.test.ts index 8457f3dc5..72aa09488 100644 --- a/www/__tests__/metHelper.test.ts +++ b/www/__tests__/metHelper.test.ts @@ -33,7 +33,7 @@ it('gets met for mode and speed', () => { it('gets custom met for mode and speed', async () => { const appConfig = await getConfig(); - await initCustomDatasetHelper(appConfig); + await initCustomDatasetHelper(appConfig!); expect(getMet('walk', 1.47523, 0)).toBe(4.3); //1.47523 mps = 3.299 mph -> 4.3 METs expect(getMet('bike', 4.5, 0)).toBe(6.8); //4.5 mps = 10.07 mph = 6.8 METs expect(getMet('unicycle', 100, 0)).toBe(0); //unkown mode, 0 METs diff --git a/www/js/config/dynamicConfig.ts b/www/js/config/dynamicConfig.ts index f92239170..361b0d38c 100644 --- a/www/js/config/dynamicConfig.ts +++ b/www/js/config/dynamicConfig.ts @@ -7,13 +7,13 @@ import { AppConfig } from '../types/appConfigTypes'; export const CONFIG_PHONE_UI = 'config/app_ui_config'; export const CONFIG_PHONE_UI_KVSTORE = 'CONFIG_PHONE_UI'; -export let storedConfig: AppConfig | null = null; +export let _promisedConfig: Promise | undefined; export let configChanged = false; export const setConfigChanged = (b) => (configChanged = b); // used to test multiple configs, not used outside of test -export const _test_resetStoredConfig = () => { - storedConfig = null; +export const _test_resetPromisedConfig = () => { + _promisedConfig = undefined; }; /** @@ -261,7 +261,7 @@ export function loadNewConfig(newToken: string, existingVersion?: number): Promi .then(([result, kvStoreResult]) => { logDebug(`UI_CONFIG: Stored dynamic config in KVStore successfully, result = ${JSON.stringify(kvStoreResult)}`); - storedConfig = toSaveConfig; + _promisedConfig = Promise.resolve(toSaveConfig); configChanged = true; return true; }) @@ -298,25 +298,25 @@ export const resetDataAndRefresh = () => * @returns The app config, either from a cached copy, retrieved from local storage, or retrieved * from user cache with getDocument() */ -export function getConfig(): Promise { - if (storedConfig) return Promise.resolve(storedConfig); - return storageGet(CONFIG_PHONE_UI_KVSTORE).then((config) => { +export function getConfig(): Promise { + if (_promisedConfig) return _promisedConfig; + let promise = storageGet(CONFIG_PHONE_UI_KVSTORE).then((config) => { if (config && Object.keys(config).length) { - logDebug('Got config from KVStore: ' + JSON.stringify(config)); - storedConfig = _backwardsCompatFill(config); - return storedConfig; + logDebug('Got config from KVStore: '); + return _backwardsCompatFill(config); } logDebug('No config found in KVStore, fetching from native storage'); return window['cordova'].plugins.BEMUserCache.getDocument(CONFIG_PHONE_UI, false).then( (config) => { if (config && Object.keys(config).length) { logDebug('Got config from native storage: ' + JSON.stringify(config)); - storedConfig = _backwardsCompatFill(config); - return storedConfig; + return _backwardsCompatFill(config); } logWarn('No config found in native storage either. Returning null'); return null; }, ); }); + _promisedConfig = promise; + return promise; } diff --git a/www/js/survey/enketo/enketoHelper.ts b/www/js/survey/enketo/enketoHelper.ts index e90354856..48c2b3509 100644 --- a/www/js/survey/enketo/enketoHelper.ts +++ b/www/js/survey/enketo/enketoHelper.ts @@ -57,12 +57,10 @@ export type EnketoUserInputEntry = UserInputEntry; const LABEL_FUNCTIONS = { UseLabelTemplate: async (xmlDoc: XMLDocument, name: string) => { - let appConfig = await getConfig(); - const configSurveys = appConfig.survey_info.surveys; - - const config = configSurveys[name]; // config for this survey + const appConfig = await getConfig(); + const config = appConfig?.survey_info?.surveys?.[name]; // config for this survey const lang = i18next.resolvedLanguage || 'en'; - const labelTemplate = config.labelTemplate?.[lang]; + const labelTemplate = config?.labelTemplate?.[lang]; if (!labelTemplate) return 'Answered'; // no template given in config if (!config.labelVars) return labelTemplate; // if no vars given, nothing to interpolate, From 74986bce877da0146585b81c578bfb6237bf9e30 Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 16 Aug 2024 15:09:31 -0400 Subject: [PATCH 4/6] tidy more logs https://github.com/e-mission/e-mission-phone/pull/1165 --- www/js/diary/LabelTab.tsx | 3 ++- www/js/metrics/customMetricsHelper.ts | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/www/js/diary/LabelTab.tsx b/www/js/diary/LabelTab.tsx index b368adc0c..01054bcd9 100644 --- a/www/js/diary/LabelTab.tsx +++ b/www/js/diary/LabelTab.tsx @@ -99,7 +99,8 @@ const LabelTab = () => { // if either the trip before or after is displayed, then keep the untracked time return prevTripDisplayed || nextTripDisplayed; }); - logDebug('After filtering, entriesToDisplay = ' + JSON.stringify(entriesToDisplay)); + logDebug(`After filtering, displaying ${entriesToDisplay.length} + out of ${allEntries.length} entries`); } else { logDebug('No active filter, displaying all entries'); } diff --git a/www/js/metrics/customMetricsHelper.ts b/www/js/metrics/customMetricsHelper.ts index 096a62cb4..b5f099d06 100644 --- a/www/js/metrics/customMetricsHelper.ts +++ b/www/js/metrics/customMetricsHelper.ts @@ -95,9 +95,8 @@ function populateCustomFootprints() { */ export async function initCustomDatasetHelper(newConfig: AppConfig) { try { - logDebug('initializing custom datasets with config' + newConfig); + logDebug('initializing custom datasets'); const labelOptions = await getLabelOptions(newConfig); - logDebug('In custom metrics, label options = ' + JSON.stringify(labelOptions)); _labelOptions = labelOptions; populateCustomMETs(); populateCustomFootprints(); From 04d3f85e405a3da609623eeade2a2c2fec5d360d Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 16 Aug 2024 17:10:50 -0400 Subject: [PATCH 5/6] tidy logs on metrics tab https://github.com/e-mission/e-mission-phone/pull/1165 --- www/js/components/Chart.tsx | 6 ------ www/js/metrics/CarbonFootprintCard.tsx | 10 +++++----- www/js/metrics/CarbonTextCard.tsx | 10 +++++----- www/js/metrics/MetricsTab.tsx | 1 - 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/www/js/components/Chart.tsx b/www/js/components/Chart.tsx index e86ef794b..3a97ab697 100644 --- a/www/js/components/Chart.tsx +++ b/www/js/components/Chart.tsx @@ -146,9 +146,6 @@ const Chart = ({ ? {} : { callback: (value, i) => { - logDebug(`Horizontal axis callback: i = ${i}; - chartDatasets = ${JSON.stringify(chartDatasets)}; - chartDatasets[0].data = ${JSON.stringify(chartDatasets[0].data)}`); //account for different data possiblities const label = chartDatasets[0].data[i]?.y || chartDatasets[i].data[0]?.y; @@ -185,9 +182,6 @@ const Chart = ({ ? {} : { callback: (value, i) => { - logDebug(`Vertical axis callback: i = ${i}; - chartDatasets = ${JSON.stringify(chartDatasets)}; - chartDatasets[0].data = ${JSON.stringify(chartDatasets[0].data)}`); //account for different data possiblities - one mode per week, one mode both weeks, mixed weeks const label = chartDatasets[0].data[i]?.x || chartDatasets[i].data[0]?.x; diff --git a/www/js/metrics/CarbonFootprintCard.tsx b/www/js/metrics/CarbonFootprintCard.tsx index 9624e10df..211abcc29 100644 --- a/www/js/metrics/CarbonFootprintCard.tsx +++ b/www/js/metrics/CarbonFootprintCard.tsx @@ -132,12 +132,12 @@ const CarbonFootprintCard = ({ userMetrics, aggMetrics }: Props) => { // Issue 422: // https://github.com/e-mission/e-mission-docs/issues/422 let aggCarbonData: MetricsSummary[] = []; - for (let i in aggThisWeekSummary) { - aggCarbonData.push(aggThisWeekSummary[i]); - if (isNaN(aggCarbonData[i].values)) { + for (let summaryEntry of aggThisWeekSummary) { + aggCarbonData.push(summaryEntry); + if (isNaN(summaryEntry.values)) { logWarn(`WARNING in calculating groupCarbonRecords: value is NaN for mode - ${aggCarbonData[i].key}, changing to 0`); - aggCarbonData[i].values = 0; + ${summaryEntry.key}, changing to 0`); + summaryEntry.values = 0; } } diff --git a/www/js/metrics/CarbonTextCard.tsx b/www/js/metrics/CarbonTextCard.tsx index ca9f50fdc..15234d530 100644 --- a/www/js/metrics/CarbonTextCard.tsx +++ b/www/js/metrics/CarbonTextCard.tsx @@ -108,12 +108,12 @@ const CarbonTextCard = ({ userMetrics, aggMetrics }: Props) => { // Issue 422: // https://github.com/e-mission/e-mission-docs/issues/422 let aggCarbonData: MetricsSummary[] = []; - for (let i in aggThisWeekSummary) { - aggCarbonData.push(aggThisWeekSummary[i]); - if (isNaN(aggCarbonData[i].values)) { + for (let summaryEntry of aggThisWeekSummary) { + aggCarbonData.push(summaryEntry); + if (isNaN(summaryEntry.values)) { logWarn(`WARNING in calculating groupCarbonRecords: value is NaN for mode - ${aggCarbonData[i].key}, changing to 0`); - aggCarbonData[i].values = 0; + ${summaryEntry.key}, changing to 0`); + summaryEntry.values = 0; } } diff --git a/www/js/metrics/MetricsTab.tsx b/www/js/metrics/MetricsTab.tsx index 3d4748f67..2c70d3a83 100644 --- a/www/js/metrics/MetricsTab.tsx +++ b/www/js/metrics/MetricsTab.tsx @@ -81,7 +81,6 @@ async function fetchAggMetrics( }; return getAggregateData('result/metrics/yyyy_mm_dd', query, appConfig.server) .then((response) => { - logDebug('MetricsTab: received aggMetrics'); console.debug('MetricsTab: received aggMetrics', response); return response as MetricsData; }) From fd49f8b5d6f8d8b0fb3cdad41dceb08cc550e6dd Mon Sep 17 00:00:00 2001 From: Jack Greenlee Date: Fri, 16 Aug 2024 17:15:09 -0400 Subject: [PATCH 6/6] tidy / add logs to commHelper functions This is one area we have been lacking in logs. Adds a standardized way to log on each commHelper function, including: the function called, the arguments passed, the message posted to the server (if applicable), and the result of the call For functions with lightweight response data, the full JSON is logged; for heavy response data, the log just counts # of entries I commented out unused commHelper functions --- www/js/services/commHelper.ts | 358 +++++++++++++++++++--------------- 1 file changed, 202 insertions(+), 156 deletions(-) diff --git a/www/js/services/commHelper.ts b/www/js/services/commHelper.ts index 012089313..086252cc2 100644 --- a/www/js/services/commHelper.ts +++ b/www/js/services/commHelper.ts @@ -3,6 +3,11 @@ import { displayError, logDebug } from '../plugin/logger'; import { ServerConnConfig } from '../types/appConfigTypes'; import { TimestampRange } from '../types/diaryTypes'; +const log = (str, r) => { + logDebug(str); + return r; +}; + /** * @param url URL endpoint for the request * @param fetchOpts (optional) options for the fetch request. If 'cache' is set to 'reload', the cache will be ignored @@ -34,7 +39,8 @@ export function getRawEntries( max_entries = undefined, trunc_method = 'sample', ) { - return new Promise((rs, rj) => { + let prefix = `getRawEntries, args: ${JSON.stringify(Object.values(arguments))};\n\n`; + return new Promise((rs, rj) => { const msgFiller = (message) => { message.key_list = key_list; message.start_time = start_ts; @@ -44,100 +50,117 @@ export function getRawEntries( message.max_entries = max_entries; message.trunc_method = trunc_method; } - logDebug(`About to return message ${JSON.stringify(message)}`); + logDebug(prefix + `message: ${JSON.stringify(message)}`); }; - logDebug('getRawEntries: about to get pushGetJSON for the timestamp'); + logDebug(prefix + 'calling pushGetJSON on /datastreams/find_entries/timestamp'); window['cordova'].plugins.BEMServerComm.pushGetJSON( '/datastreams/find_entries/timestamp', msgFiller, rs, rj, ); - }).catch((error) => { - error = `While getting raw entries, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${r.phone_data.length} entries`, r)) + .catch((error) => { + error = `While getting raw entries, ${error}`; + throw error; + }); } -// time_key is typically metadata.write_ts or data.ts -export function getRawEntriesForLocalDate( - key_list, - start_ts, - end_ts, - time_key = 'metadata.write_ts', - max_entries = undefined, - trunc_method = 'sample', -) { - return new Promise((rs, rj) => { - const msgFiller = (message) => { - message.key_list = key_list; - message.from_local_date = DateTime.fromSeconds(start_ts).toObject(); - message.to_local_date = DateTime.fromSeconds(end_ts).toObject(); - message.key_local_date = time_key; - if (max_entries !== undefined) { - message.max_entries = max_entries; - message.trunc_method = trunc_method; - } - logDebug('About to return message ' + JSON.stringify(message)); - }; - logDebug('getRawEntries: about to get pushGetJSON for the timestamp'); - window['cordova'].plugins.BEMServerComm.pushGetJSON( - '/datastreams/find_entries/local_date', - msgFiller, - rs, - rj, - ); - }).catch((error) => { - error = 'While getting raw entries for local date, ' + error; - throw error; - }); -} +// // time_key is typically metadata.write_ts or data.ts +// export function getRawEntriesForLocalDate( +// key_list, +// start_ts, +// end_ts, +// time_key = 'metadata.write_ts', +// max_entries = undefined, +// trunc_method = 'sample', +// ) { +// let prefix = `getRawEntriesForLocalDate, args: ${JSON.stringify(Object.values(arguments))};\n\n`; +// return new Promise((rs, rj) => { +// const msgFiller = (message) => { +// message.key_list = key_list; +// message.from_local_date = DateTime.fromSeconds(start_ts).toObject(); +// message.to_local_date = DateTime.fromSeconds(end_ts).toObject(); +// message.key_local_date = time_key; +// if (max_entries !== undefined) { +// message.max_entries = max_entries; +// message.trunc_method = trunc_method; +// } +// logDebug(prefix + `message: ${JSON.stringify(message)}`); +// }; +// logDebug(prefix + 'calling pushGetJSON on /datastreams/find_entries/local_date'); +// window['cordova'].plugins.BEMServerComm.pushGetJSON( +// '/datastreams/find_entries/local_date', +// msgFiller, +// rs, +// rj, +// ); +// }) +// .then((r) => log(prefix + `got ${r.phone_data.length} entries`, r)) +// .catch((error) => { +// error = 'While getting raw entries for local date, ' + error; +// throw error; +// }); +// } export function getPipelineRangeTs(): Promise { - return new Promise((rs: (rangeTs: TimestampRange) => void, rj) => { - logDebug('getting pipeline range timestamps'); + let prefix = `getPipelineRangeTs, args: ${JSON.stringify(Object.values(arguments))};\n\n`; + return new Promise((rs, rj) => { + logDebug(prefix + 'calling getUserPersonalData on /pipeline/get_range_ts'); window['cordova'].plugins.BEMServerComm.getUserPersonalData('/pipeline/get_range_ts', rs, rj); - }).catch((error) => { - error = `While getting pipeline range timestamps, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = `While getting pipeline range timestamps, ${error}`; + throw error; + }); } -export function getPipelineCompleteTs() { - return new Promise((rs, rj) => { - logDebug('getting pipeline complete timestamp'); - window['cordova'].plugins.BEMServerComm.getUserPersonalData( - '/pipeline/get_complete_ts', - rs, - rj, - ); - }).catch((error) => { - error = `While getting pipeline complete timestamp, ${error}`; - throw error; - }); -} +// export function getPipelineCompleteTs() { +// let prefix = `getPipelineCompleteTs, args: ${JSON.stringify(Object.values(arguments))};\n\n`; +// return new Promise((rs, rj) => { +// logDebug(prefix + 'calling getUserPersonalData on /pipeline/get_complete_ts'); +// window['cordova'].plugins.BEMServerComm.getUserPersonalData( +// '/pipeline/get_complete_ts', +// rs, +// rj, +// ); +// }) +// .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) +// .catch((error) => { +// error = `While getting pipeline complete timestamp, ${error}`; +// throw error; +// }); +// } -export function getMetrics(timeType: 'timestamp' | 'local_date', metricsQuery) { - return new Promise((rs, rj) => { - const msgFiller = (message) => { - for (let key in metricsQuery) { - message[key] = metricsQuery[key]; - } - }; - window['cordova'].plugins.BEMServerComm.pushGetJSON( - `/result/metrics/${timeType}`, - msgFiller, - rs, - rj, - ); - }).catch((error) => { - error = `While getting metrics, ${error}`; - throw error; - }); -} +// export function getMetrics(timeType: 'timestamp' | 'local_date', metricsQuery) { +// let prefix = `getMetrics, args: ${JSON.stringify(Object.values(arguments))};\n\n`; +// return new Promise((rs, rj) => { +// const msgFiller = (message) => { +// for (let key in metricsQuery) { +// message[key] = metricsQuery[key]; +// } +// logDebug(prefix + `message: ${JSON.stringify(message)}`); +// }; +// logDebug(prefix + `calling pushGetJSON on /result/metrics/${timeType}`); +// window['cordova'].plugins.BEMServerComm.pushGetJSON( +// `/result/metrics/${timeType}`, +// msgFiller, +// rs, +// rj, +// ); +// }) +// .then((r) => log(prefix + `got ${r.phone_data.length} entries`, r)) +// .catch((error) => { +// error = `While getting metrics, ${error}`; +// throw error; +// }); +// } export function getAggregateData(path: string, query, serverConnConfig?: ServerConnConfig) { - return new Promise((rs, rj) => { + let prefix = `getAggregateData, args: ${JSON.stringify(Object.values(arguments))};\n\n`; + return new Promise((rs, rj) => { // when app config does not have "server", localhost is used and no user authentication is required serverConnConfig ||= { connectUrl: 'http://localhost:8080' as any, @@ -154,6 +177,7 @@ export function getAggregateData(path: string, query, serverConnConfig?: ServerC data: query, responseType: 'json', }; + logDebug(prefix + `calling http.sendRequest on ${fullUrl}`); window['cordova'].plugin.http.sendRequest( fullUrl, options, @@ -165,28 +189,42 @@ export function getAggregateData(path: string, query, serverConnConfig?: ServerC }, ); } else { - logDebug(`getting aggregate data with user authentication from ${fullUrl} - with arguments ${JSON.stringify(query)}`); + logDebug( + prefix + + `calling getUserPersonalData on ${fullUrl}; + query: ${JSON.stringify(query)}`, + ); const msgFiller = (message) => Object.assign(message, query); window['cordova'].plugins.BEMServerComm.pushGetJSON(`/${path}`, msgFiller, rs, rj); } - }).catch((error) => { - error = `While getting aggregate data, ${error}`; - throw error; - }); + }) + .then((r) => { + let summary = Object.entries(r).map(([k, v]: any) => ({ [k]: `<${v.length} entries>` })); + return log(prefix + `got ${JSON.stringify(summary)}`, r); + }) + .catch((error) => { + error = `While getting aggregate data, ${error}`; + throw error; + }); } export function registerUser() { + let prefix = `registerUser, args: ${JSON.stringify(Object.values(arguments))};\n\n`; return new Promise((rs, rj) => { + logDebug(prefix + 'calling getUserPersonalData on /profile/create'); window['cordova'].plugins.BEMServerComm.getUserPersonalData('/profile/create', rs, rj); - }).catch((error) => { - error = `While registering user, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = `While registering user, ${error}`; + throw error; + }); } export function updateUser(updateDoc) { + let prefix = `updateUser, args: ${JSON.stringify(Object.values(arguments))};\n\n`; return new Promise((rs, rj) => { + logDebug(prefix + 'calling postUserPersonalData on /profile/update'); window['cordova'].plugins.BEMServerComm.postUserPersonalData( '/profile/update', 'update_doc', @@ -194,48 +232,56 @@ export function updateUser(updateDoc) { rs, rj, ); - }).catch((error) => { - error = `While updating user, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = `While updating user, ${error}`; + throw error; + }); } export function getUser() { + let prefix = `getUser, args: ${JSON.stringify(Object.values(arguments))};\n\n`; return new Promise((rs, rj) => { + logDebug(prefix + 'calling getUserPersonalData on /profile/get'); window['cordova'].plugins.BEMServerComm.getUserPersonalData('/profile/get', rs, rj); - }).catch((error) => { - error = `While getting user, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = `While getting user, ${error}`; + throw error; + }); } -export function putOne(key, data) { - const nowTs = DateTime.now().toUnixInteger(); - const metadata = { - write_ts: nowTs, - read_ts: nowTs, - time_zone: DateTime.local().zoneName, - type: 'message', - key: key, - platform: window['device'].platform, - }; - const entryToPut = { metadata, data }; - return new Promise((rs, rj) => { - window['cordova'].plugins.BEMServerComm.postUserPersonalData( - '/usercache/putone', - 'the_entry', - entryToPut, - rs, - rj, - ); - }).catch((error) => { - error = 'While putting one entry, ' + error; - throw error; - }); -} +// export function putOne(key, data) { +// const nowTs = DateTime.now().toUnixInteger(); +// const metadata = { +// write_ts: nowTs, +// read_ts: nowTs, +// time_zone: DateTime.local().zoneName, +// type: 'message', +// key: key, +// platform: window['device'].platform, +// }; +// const entryToPut = { metadata, data }; +// return new Promise((rs, rj) => { +// window['cordova'].plugins.BEMServerComm.postUserPersonalData( +// '/usercache/putone', +// 'the_entry', +// entryToPut, +// rs, +// rj, +// ); +// }).catch((error) => { +// error = 'While putting one entry, ' + error; +// throw error; +// }); +// } export function getUserCustomLabels(keys) { + let prefix = `getUserCustomLabels, args: ${JSON.stringify(Object.values(arguments))};\n\n`; return new Promise((rs, rj) => { + logDebug(prefix + 'calling postUserPersonalData on /customlabel/get'); window['cordova'].plugins.BEMServerComm.postUserPersonalData( '/customlabel/get', 'keys', @@ -243,67 +289,67 @@ export function getUserCustomLabels(keys) { rs, rj, ); - }).catch((error) => { - error = 'While getting labels, ' + error; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = 'While getting labels, ' + error; + throw error; + }); } -export function insertUserCustomLabel(key, newLabel) { - const insertedLabel = { - key: key, - label: newLabel, - }; +export function insertUserCustomLabel(key, label) { + let prefix = `insertUserCustomLabel, args: ${JSON.stringify(Object.values(arguments))};\n\n`; return new Promise((rs, rj) => { + logDebug(prefix + 'calling postUserPersonalData on /customlabel/insert'); window['cordova'].plugins.BEMServerComm.postUserPersonalData( '/customlabel/insert', 'inserted_label', - insertedLabel, + { key, label }, rs, rj, ); - }).catch((error) => { - error = `While inserting one ${key}, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = `While inserting one ${key}, ${error}`; + throw error; + }); } -export function updateUserCustomLabel(key, oldLabel, newLabel, isNewLabelMustAdded) { - const updatedLabel = { - key: key, - old_label: oldLabel, - new_label: newLabel, - is_new_label_must_added: isNewLabelMustAdded, - }; +export function updateUserCustomLabel(key, old_label, new_label, is_new_label_must_added) { + let prefix = `updateUserCustomLabel, args: ${JSON.stringify(Object.values(arguments))};\n\n`; return new Promise((rs, rj) => { + logDebug(prefix + 'calling postUserPersonalData on /customlabel/update'); window['cordova'].plugins.BEMServerComm.postUserPersonalData( '/customlabel/update', 'updated_label', - updatedLabel, + { key, old_label, new_label, is_new_label_must_added }, rs, rj, ); - }).catch((error) => { - error = `While updating one ${key}, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = `While updating one ${key}, ${error}`; + throw error; + }); } -export function deleteUserCustomLabel(key, newLabel) { - const deletedLabel = { - key: key, - label: newLabel, - }; +export function deleteUserCustomLabel(key, label) { + let prefix = `deleteUserCustomLabel, args: ${JSON.stringify(Object.values(arguments))};\n\n`; return new Promise((rs, rj) => { + logDebug(prefix + 'calling postUserPersonalData on /customlabel/delete'); window['cordova'].plugins.BEMServerComm.postUserPersonalData( '/customlabel/delete', 'deleted_label', - deletedLabel, + { key, label }, rs, rj, ); - }).catch((error) => { - error = `While deleting one ${key}, ${error}`; - throw error; - }); + }) + .then((r) => log(prefix + `got ${JSON.stringify(r)}`, r)) + .catch((error) => { + error = `While deleting one ${key}, ${error}`; + throw error; + }); }