a configurable logger decorator to automate function logs, compatible with winston, n-logger, n-mask-logger, etc.
It has been consolidated into n-express-monitor, please use that instead unless you're curious about things under the hood or want to customise your own tool chain
npm i @financial-times/n-auto-logger --save
import { setupLoggerInstance } from '@financial-times/n-auto-logger';
import winston from 'winston'; // you can use any instance as long as it has .info, .warn, .error method
setupLoggerInstance(winston); // if logger instance not set, it would use n-logger by default
A top level execution is categorised as an Operation, this can be an express middleware or controller function. Any lower level execution is categorised as an Action, and a two-level model of operation-action is encouraged.
With different log level settings, it would log the start, success/failure status
of the function execution, function names to scope
the operation/action, description of the error
and params you need to recreate
the error.
import { compose, autoNext, logOperation } from '@financial-times/n-auto-logger';
const operation = (req, res) => {
//let the error to be thrown
};
export default compose(
autoNext,
logOperation,
)(operation);
import { logAction } from '@financial-times/n-auto-logger';
const action = (params: Object, meta: Object) => {}; // the function signature needs to follow the convention
export default logAction(action);
const operation = ({ meta }, res, next) => {
action(param, meta); // pass the meta object from req.meta to thread operation/action
//...
};
use the requestIdMiddleware to ensure the logs are easy to thread when debugging, and this would work well with n-api-factory to pass it to up stream services.
import { requestIdMiddleware } from '@financial-times/n-auto-logger';
app.use([
requestIdMiddleware, // use it before any decorated middleware
//...decorated operation middlewares
]);
auto log level can be set in ENV_VAR with 4 options: verbose
| standard
(default) | concise
| error
.
check the example outputs
key names in meta can be ignored with settings in ENV_VAR to further concise log for specific cases
LOGGER_MUTE_FIELDS=transactionId, userId
threader
(requestId, userId)-scope
(operation, action, service)-status
(success/failure)-error
(category, status)-recreation
(params used in the function call)
based on the log, a brief next step guideline is as following:
NODE_SYSTEM_ERROR
would indicate implementation flaws in the system codebaseCUSTOM_ERROR
or 4XXFETCH_RESPONSE_ERROR
would indicate known issues happening or validation/user journey flaws in the system- 5XX
FETCH_RESPONSE_ERROR
would indicate issues potentially in the codebase of upstream systems FETCH_NETWORK_ERROR
can be caused either by configuration in current system or upstream systems
An Meta object is used throughout operation(req.meta) and action(param, meta) to thread the status of functions and its context, the following conventional key names are used:
fields | default |
---|---|
operation | operation function name |
action | action function name |
service | api client action bundle service name, use monitorService |
result | 'success' 'failure' |
category | 'FETCH_RESPONSE_ERROR' 'FETCH_NETWORK_ERROR' 'NODE_SYSTEM_ERROR' 'CUSTOM_ERROR' |
type | specify the unique error type for debugging and error handling |
status | recorded for service action call failure |
stack | error stack trace (can be ignored, as operation/action should have help you locate the scope) |
user
, handler
fields from error
or meta
object would not be logged.
User facing error message can be included in error.user
to decouple the user and debug message
throw nError({ status, message }).extend({ user: { status, message } });
.handler
field would not be logged, as it is only useful for error handler
throw nError({ status: 404 }).extend({ handler: 'REDIRECT_TO_INDEX' });
n-auto-logger
would parse different forms of the following error objects to logger-suitable format automatically(detail), while it still logs plain object and string message.
- Fetch Response Error
content-type
:application/json
,text/plain
,text/html
- Fetch (Network) Error
- Node native Error objects
- Custom objects extends native Error object
- NError
stub the logger instance instead of the whole module
import logger from '@financial-times/n-auto-logger'; // the underlying logger instance (`n-logger`)
// sinon sandbox
sandbox.stub(logger);
// jest
logger.info = jest.fn();
logger.warn = jest.fn();
logger.error = jest.fn();