diff --git a/packages/api/.env.default b/packages/api/.env.default index 1d3f690659..b58f382111 100644 --- a/packages/api/.env.default +++ b/packages/api/.env.default @@ -28,7 +28,7 @@ JWT_SCHEDULER_SECRET=Another_token_was_needed_for_the_scheduler # > https://www.npmjs.com/package/@googlemaps/google-maps-services-js # Same as the VITE_GOOGLE_MAPS_API_KEY under webapp GOOGLE_API_KEY=? - + # Most functionality is covered by the free OpenWeather API key at https://openweathermap.org/price # Note: OpenWeather may take a few hours before the api key is working # Same as the VITE_WEATHER_API_KEY under webapp @@ -108,4 +108,13 @@ OOO_END_DATE= # MOCK_ADDON_PARTNER=ESCI # Mock Ensemble irrigation prescription details -# USE_IP_MOCK_DETAILS=true \ No newline at end of file +# USE_IP_MOCK_DETAILS=true + +# Logging options +# Default log level; off to turn off all logging; possible values: error, warn, info, http, verbose, debug, silly +#LOG_LEVEL = info +# Console log level; off to disable console logging; possible values: error, warn, info, http, verbose, debug, silly +#LOG_CONSOLE_LEVEL = info +# Control Sentry logging. Sentry logging is enabled by default in non development environments. +# If you want to disable it, then uncomment the line below and set it to false. +#LOG_ENABLE_SENTRY=false \ No newline at end of file diff --git a/packages/api/src/common/logger.js b/packages/api/src/common/logger.js index d91660a013..1597d592a3 100644 --- a/packages/api/src/common/logger.js +++ b/packages/api/src/common/logger.js @@ -3,7 +3,7 @@ import DailyRotateFile from 'winston-daily-rotate-file'; import Transport from 'winston-transport'; import * as Sentry from '@sentry/node'; -const { errors, json, combine } = format; +const { errors, json, combine, cli } = format; // Add the error message as an enumerable property to return with res.json({ error }) const enumerateErrorMessage = format((info) => { @@ -13,8 +13,56 @@ const enumerateErrorMessage = format((info) => { return info; }); +/** + * Get the log level from a string or default value if not present or invalid + * @param {any} value log level string + * @param {string} defaultValue default log level + * @return {string} valid log level + */ +function getLogLevel(value, defaultValue) { + if (typeof value !== 'string') { + return defaultValue; + } + value = value.toLowerCase().trim(); + if ( + value === 'error' || + value === 'warn' || + value === 'info' || + value === 'http' || + value === 'debug' || + value === 'silly' || + value === 'off' + ) { + return value; + } + return defaultValue; +} + +/** + * Check if a string is true. + * @param {any} value string to check + * @param {boolean} defaultValue default value if not a string + * @returns {boolean} true if the string is true, false otherwise + */ +function parseBoolean(value, defaultValue) { + if (typeof value !== 'string') { + return defaultValue; + } + value = value.toLowerCase().trim(); + if (value === 'true' || value === '1' || value === 'yes' || value === 'on') { + return true; + } + if (value === 'false' || value === '0' || value === 'no' || value === 'off') { + return false; + } + return defaultValue; +} + +const rootLogLevel = getLogLevel(process.env.LOG_LEVEL, 'info'); + const logger = winston.createLogger({ - level: 'info', + level: rootLogLevel === 'off' ? 'info' : rootLogLevel, + silent: rootLogLevel === 'off', format: combine(enumerateErrorMessage(), json()), defaultMeta: { service: 'user-service' }, transports: [ @@ -24,7 +72,6 @@ const logger = winston.createLogger({ // new DailyRotateFile({ filename: './logs/error.log', level: 'error' }), new DailyRotateFile({ filename: './logs/combined.log' }), - new winston.transports.Console({ level: 'info' }), ], }); @@ -32,10 +79,13 @@ const logger = winston.createLogger({ // If we're not in production then log to the `console` with the format: // `${info.level}: ${info.message} JSON.stringify({ ...rest }) ` // -if (process.env.NODE_ENV !== 'production') { +const consoleLogLevel = getLogLevel(process.env.LOG_CONSOLE_LEVEL, 'error'); + +if (consoleLogLevel !== 'off') { logger.add( new winston.transports.Console({ - format: combine(errors(), json()), + level: consoleLogLevel, + format: combine(errors(), cli()), }), ); } @@ -61,7 +111,7 @@ class SentryTransport extends Transport { } // Report Errors to Sentry -if (process.env.NODE_ENV !== 'development') { +if (process.env.NODE_ENV !== 'development' && parseBoolean(process.env.LOG_ENABLE_SENTRY, true)) { logger.add(new SentryTransport()); }