react-app-layout
react-app-layout copied to clipboard
blah
Let's follow existing conventions as far as possible, whilst keeping thing as simple as possible, we can always add functionality We can take our cures from apache commons logging
log.error
log.warn
log.info
log.debug
In a production build, only error logs will actually log anything, other log statements will be no-ops. In a dev build or a published debug package , the other log statements will log if the configured log level determines that they should, so:
log level === 'debug' all log statements will log
log level === 'info'
log.debug
statements will not log, all other log statements will be no-ops. This will be default in dev build
log level === "warn"
neither log.debug
nor log.info
statements will log
log level === 'error'
only log.error
statements log. This is same as prod build
-- Guarding against expensive runtime args The logger implementation will ensure that those log statements that should not log do not do so, according to the configured log level. In some cases, the argument(s) passed to a log statement may themselves be expensive to compute, e.g an expensive JSON stringify or a complex constructed object. To avoid these incurring runtime cost for a log message which will not actually be logged, we will offer a set of guards
- warnEnabled
- infoEnabled
- debugEnabled
so we can code the following
import { logger} from "@finos/vuu-utils"
const log = logger('ServerProxy')
if (log.debugEnabled){
log.debug(`${buildExpensiveDebugObject().toString()}`)
}
whereas if we're just logging a simple string message, we would just use
import { logger} from "@finos/vuu-utils"
// once, at module level
const log = logger('ServerProxy')
// many times, anywhere in code
log.debug("setRange invoked")
Code which is particularly performance sensitive might want to enclose log statements (except for log.error) in a build-time env check
if (process.env.NODE_ENV === 'development'){
log.info('blah blah')
}
Such code will be entirely removed from a prod build, not even incurring the cost of a no-op function call (if such a call even has a cost once the optimising compiler does its thing ?)
configuring the log level
This will be done initially with a cookie. We can set the log level to error
, info
, warn
or debug
.
Eventually, we will want to allow configuration of category
as well, so we can offer fine-grained control of logging. What those categories are will be at the developers discretion. At least each file should create its logger with a context identifier, e.g the example above using 'ServerProxy'. Developers might want to add additional categories that span files. e.g perf
, protocol-messages
The worker requires special treatment, as code within the worker has no access to cookies, not can it access any global variables or modules initiated in the UI thread. We will inject a logging configuration object into the worker source code (the source code is loaded a string and Blob Url).
The logger implementation
The utils package should expose a logger
factory function that will return a log object with the appropriate guard properties and logging functions.
it might look something like this
// from cookie in ui thread or global config in worker thread
const logLevel = getLogLevel()
const noop = () => undefined;
const debugEnabled = logLevel === 'debug'
const infoEnabled = debugEnabled || logLevel === 'info'
const warnEnabled = infoEnabled || logLevel === 'warn'
return function logger(category){
return {
debugEnabled,
infoEnabled,
warnEnabled,
info: infoEnabled ? (message)=> console.info('[category] ' + message) : noop
etc
}
Might want to throw a formatted timestamp into the messages too ?
Eventually, we will want to allow the logger factory to be pluggable, probably through React Context (although again the worker will be a special case). Fow now a simple console logger will suffice.