From cc23676f9b3303e5128e12393b565c30f514ad3a Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Wed, 10 Apr 2019 10:53:12 -0500 Subject: [PATCH] web: clean up logging usage, parameterize with ENV vars. --- web/src/app.ts | 70 ++++++++++++++----- web/src/main.ts | 4 ++ web/src/services/logging/api-log-appender.ts | 4 +- .../services/logging/console-log-appender.ts | 6 +- web/src/services/logging/log-appender.ts | 1 + web/src/services/logging/log-message.ts | 2 +- web/src/services/pm-api-client.ts | 6 +- web/src/store-modules/api-token.ts | 2 +- web/src/store-modules/measurement.ts | 2 +- web/src/store-modules/user.ts | 3 +- 10 files changed, 75 insertions(+), 25 deletions(-) diff --git a/web/src/app.ts b/web/src/app.ts index ecda6f4..e1c1220 100644 --- a/web/src/app.ts +++ b/web/src/app.ts @@ -4,6 +4,8 @@ import { logService, LogLevel, ApiLogAppender, ConsoleLogAppender } from '@/serv import { authStore } from '@/store'; import { User } from '@/models'; +const logger = logService.getLogger('/app'); + @Component({ components: { NavBar @@ -11,25 +13,12 @@ import { User } from '@/models'; }) export default class App extends Vue { - private consoleLogAppender: ConsoleLogAppender; - private apiLogAppender: ApiLogAppender; + private apiLogAppender!: ApiLogAppender; + private consoleLogAppender!: ConsoleLogAppender; constructor() { super(); - - // Setup application logging. - this.consoleLogAppender = new ConsoleLogAppender(LogLevel.ALL); - this.apiLogAppender = new ApiLogAppender( - process.env.VUE_APP_PM_API_BASE + '/log/batch', '', LogLevel.WARN); - logService.ROOT_LOGGER.appenders.push(this.apiLogAppender, this.consoleLogAppender); - - // TODO: prod/dev config settings for logging? - this.apiLogAppender.batchSize = 1; - this.apiLogAppender.minimumTimePassedInSec = 5; - - // Check for existing session cookie. - /*tslint:disable:no-empty*/ - authStore.findLocalToken().catch(() => {}); + this.configureLoggers(); } private get authToken(): string | null { @@ -38,6 +27,55 @@ export default class App extends Vue { @Watch('authToken') private onAuthTokenChange(val: string | undefined , oldVal: string | undefined) { + // If the user wasn't logged in initially, or their session expires, we + // want to catch the new token for our API log appender. if (val) { this.apiLogAppender.authToken = val; } } + + private configureLoggers(): void { + + let commonLevel = LogLevel.WARN; + if (LogLevel.hasOwnProperty(process.env.VUE_APP_LOG_LEVEL)) { + commonLevel = (LogLevel[process.env.VUE_APP_LOG_LEVEL] as unknown) as LogLevel; + } + + // Because modules like the router will start logging messages before this + // component is initialized, the console appender is initialized and added + // in main.ts + this.consoleLogAppender = logService.ROOT_LOGGER.appenders[0]; + + // We create the API log appender (need credentials anyways) + this.apiLogAppender = new ApiLogAppender( + process.env.VUE_APP_PM_API_BASE + '/log/batch', + this.authToken || '', // user may already be logged in and have a token + LogLevel.WARN); + + logService.ROOT_LOGGER.appenders.push(this.apiLogAppender); + + if (LogLevel.hasOwnProperty(process.env.VUE_APP_API_LOG_LEVEL)) { + this.apiLogAppender.threshold = (LogLevel[process.env.VUE_APP_API_LOG_LEVEL] as unknown) as LogLevel; + } else { + this.apiLogAppender.threshold = commonLevel; + } + + if (LogLevel.hasOwnProperty(process.env.VUE_APP_CONSOLE_LOG_LEVEL)) { + this.consoleLogAppender.threshold = (LogLevel[process.env.VUE_APP_CONSOLE_LOG_LEVEL] as unknown) as LogLevel; + } else { + this.consoleLogAppender.threshold = commonLevel; + } + + try { + this.apiLogAppender.batchSize = + parseInt(process.env.VUE_APP_API_LOG_BATCH_SIZE, 10); + } catch { + this.apiLogAppender.batchSize = 5; + } + + try { + this.apiLogAppender.minimumTimePassedInSec + = parseInt(process.env.VUE_APP_API_LOG_MIN_TIME_PASSED_IN_SEC, 10); + } catch { + this.apiLogAppender.minimumTimePassedInSec = 5; + } + } } diff --git a/web/src/main.ts b/web/src/main.ts index b2d1cb6..35369f8 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -10,11 +10,15 @@ import SmartTable from 'vuejs-smart-table'; import ApexChart from 'vue-apexcharts'; import './registerServiceWorker'; +import { logService, LogLevel, ApiLogAppender, ConsoleLogAppender } from '@/services/logging'; Vue.component('fa-icon', FontAwesomeIcon); Vue.component('apex-chart', ApexChart); Vue.use(SmartTable); +const consoleLogAppender = new ConsoleLogAppender(LogLevel.ALL); +logService.ROOT_LOGGER.appenders.push(consoleLogAppender); + new Vue({ router, store, diff --git a/web/src/services/logging/api-log-appender.ts b/web/src/services/logging/api-log-appender.ts index 19de0fe..3979e09 100644 --- a/web/src/services/logging/api-log-appender.ts +++ b/web/src/services/logging/api-log-appender.ts @@ -15,13 +15,15 @@ export class ApiLogAppender implements LogAppender { public batchSize = 10; public minimumTimePassedInSec = 60; public maximumTimePassedInSec = 120; + public threshold = LogLevel.ALL; private http = Axios.create(); private msgBuffer: ApiMessage[] = []; private lastSent = 0; - constructor(public readonly apiEndpoint: string, public authToken?: string, public threshold?: LogLevel) { + constructor(public readonly apiEndpoint: string, public authToken?: string, threshold?: LogLevel) { setInterval(this.checkPost, 1000); + if (threshold) { this.threshold = threshold; } } public appendMessage(msg: LogMessage): void { diff --git a/web/src/services/logging/console-log-appender.ts b/web/src/services/logging/console-log-appender.ts index 6a07a1d..6994b41 100644 --- a/web/src/services/logging/console-log-appender.ts +++ b/web/src/services/logging/console-log-appender.ts @@ -4,7 +4,11 @@ import Logger from './logger'; import LogAppender from './log-appender'; export class ConsoleLogAppender implements LogAppender { - constructor(public threshold?: LogLevel) {} + public threshold = LogLevel.ALL; + + constructor(threshold?: LogLevel) { + if (threshold) { this.threshold = threshold; } + } public appendMessage(msg: LogMessage): void { if (this.threshold && msg.level < this.threshold) { return; } diff --git a/web/src/services/logging/log-appender.ts b/web/src/services/logging/log-appender.ts index 8b594c1..3e2c0da 100644 --- a/web/src/services/logging/log-appender.ts +++ b/web/src/services/logging/log-appender.ts @@ -1,5 +1,6 @@ import { LogLevel, LogMessage } from './log-message'; import Logger from './logger'; export default interface LogAppender { + threshold: LogLevel; appendMessage(message: LogMessage): void; } diff --git a/web/src/services/logging/log-message.ts b/web/src/services/logging/log-message.ts index f5d0a5c..b7cad42 100644 --- a/web/src/services/logging/log-message.ts +++ b/web/src/services/logging/log-message.ts @@ -1,4 +1,4 @@ -export enum LogLevel { ALL = 0, DEBUG, LOG, INFO, WARN, ERROR, FATAL } +export enum LogLevel { ALL = 0, TRACE, DEBUG, LOG, INFO, WARN, ERROR, FATAL } export interface LogMessage { scope: string; diff --git a/web/src/services/pm-api-client.ts b/web/src/services/pm-api-client.ts index 169741a..f3f603e 100644 --- a/web/src/services/pm-api-client.ts +++ b/web/src/services/pm-api-client.ts @@ -3,9 +3,10 @@ import assign from 'lodash.assign'; import { ApiToken, LoginSubmit, Measure, MeasureConfig, Measurement, MeasurementMeta, User } from '@/models'; import { Logger, logService } from '@/services/logging'; +const logger = logService.getLogger('services/pm-api-client'); + export class PmApiClient { private http: AxiosInstance; - private log: Logger; constructor(apiBase: string) { this.http = Axios.create({ @@ -19,8 +20,7 @@ export class PmApiClient { */ }); - this.log = logService.getLogger('services/pm-api-client'); - this.log.trace('Initialized PmApiClient'); + logger.trace('Initialized PmApiClient'); } public setAuthToken(authToken: string) { diff --git a/web/src/store-modules/api-token.ts b/web/src/store-modules/api-token.ts index cd04287..51f061b 100644 --- a/web/src/store-modules/api-token.ts +++ b/web/src/store-modules/api-token.ts @@ -9,7 +9,7 @@ import api from '@/services/pm-api-client'; import { logService } from '@/services/logging'; import { ApiToken } from '@/models'; -const log = logService.getLogger('/store-modules/api-tokens'); +const logger = logService.getLogger('/store-modules/api-tokens'); @Module({ namespaced: true, name: 'apiToken' }) export class ApiTokenStoreModule extends VuexModule { diff --git a/web/src/store-modules/measurement.ts b/web/src/store-modules/measurement.ts index 7bdea4b..a82892b 100644 --- a/web/src/store-modules/measurement.ts +++ b/web/src/store-modules/measurement.ts @@ -26,7 +26,7 @@ export class MeasurementStoreModule extends VuexModule { @Action({ rawError: true }) public async fetchMeasurements(measure: Measure) { - logger.debug('Fetching measurements for measure ' + measure.id); + logger.trace('Fetching measurements for measure ' + measure.id); const measurements = await api.getMeasurements(measure.slug); // assumption: always returns at least [] this.context.commit('SET_MEASUREMENTS', { measure, measurements }); } diff --git a/web/src/store-modules/user.ts b/web/src/store-modules/user.ts index 244be75..a03d5cb 100644 --- a/web/src/store-modules/user.ts +++ b/web/src/store-modules/user.ts @@ -8,7 +8,7 @@ import api from '@/services/pm-api-client'; import { logService } from '@/services/logging'; import { authStore } from '@/store'; -const log = logService.getLogger('/store-modules/user'); +const logger = logService.getLogger('/store-modules/user'); @Module({ namespaced: true, name: 'user' }) export class UserStoreModule extends VuexModule { @@ -17,6 +17,7 @@ export class UserStoreModule extends VuexModule { @MutationAction({ mutate: ['user'], rawError: true }) public async fetchUser() { + logger.trace('Fetching current user record.'); return { user: await api.getUser() }; }