// @flow // NOTE: dont use Module here, this class is used by Module import os from 'os' import type AWSClient from './AWSClient' import type { StatNameMode } from './InfluxDBClient' import { pad } from './stringUtils' import InfluxDBClient from './InfluxDBClient' import S3Logger from './S3Logger' const ORDERED_LOG_LEVELS = ['debug', 'info', 'warn', 'error'] const HOSTNAME = os.hostname() type SystemConfig = {| env: string, influxDBs?: ?Array<{ statNameMode: StatNameMode, host: string, dbName: string, flushIntervalMS?: ?number, }>, lifesignIntervalMS?: ?number, logLevel?: 'debug' | 'info' | 'warn' | 'error', aws: { accountId: string, defaultRegion: string, profile?: ?string, }, system: string, component: string, ver: string, s3Logging?: ?{ noHTTPS?: boolean, host: string, dataFieldsToPromote?: ?{ [id: string]: string }, dataFieldsToRemove?: ?Array, }, trackVitalsIntervalMS?: ?number, // trackingSchema?: ?number, |} export default class System { static activeLogLevels: Array static runId: string static influxDBClients: Array static _s3logger: ?S3Logger static _config: SystemConfig static _awsClient: AWSClient static async setConfig(systemConfig: SystemConfig) { System._config = { // det default values logLevel: 'info', system: 'none', ...systemConfig, } System.activeLogLevels = ORDERED_LOG_LEVELS.slice(ORDERED_LOG_LEVELS.indexOf(System._config.logLevel)) System.runId = `${pad(Math.round((Date.now() - new Date((new Date()).getFullYear(), 0, 1).getTime()) / 1000), 8)}-${pad(Math.floor(Math.random() * 10000), 4)}` // seconds since start of year // init InfluxDBClient System.influxDBClients = (System._config.influxDBs || []).map(idbConfig => new InfluxDBClient( idbConfig.host, idbConfig.dbName, idbConfig.statNameMode, idbConfig.flushIntervalMS, { system: System._config.system, component: System._config.component, hostname: HOSTNAME, env: System._config.env, }) ) System._s3logger = new S3Logger({ noHTTPS: (System._config.s3Logging || {}).noHTTPS, host: (System._config.s3Logging || {}).host, dataFieldsToPromote: (System._config.s3Logging || {}).dataFieldsToPromote, dataFieldsToRemove: (System._config.s3Logging || {}).dataFieldsToRemove, systemMeta: { hostname: HOSTNAME, system: System._config.system, component: System._config.component, env: System._config.env, run_id: System.runId, ver: System._config.ver, }, }) // track 'start' await Promise.all(System.influxDBClients.map(idbClient => idbClient.trackMetrics([{ statName: 'appStart', dims: { module: 'System', }, value: 1, }]))) } static getConfig(): SystemConfig { if (!System._config) { throw new Error('System config accessed before set') } return System._config } static setAWSClient(awsClient: AWSClient) { System._awsClient = awsClient } static queueLogRecord(logObj: Object): void { if (System._s3logger) System._s3logger.queueLogRecord(logObj) } static async flush(): Promise { await Promise.all([ (async () => { if (System._s3logger) await System._s3logger.flushLogs() })(), ...System.influxDBClients.map(idbClient => (async () => { await idbClient.trackMetrics([{ statName: 'appEnd', dims: { module: 'System' }, value: 1, }]) await idbClient.flushMetrics() })()), ]) } }