# SKUtopia Logger

SKUtopia Logger enables the tracing of requests across servers and throughout applications in Express.js. It enables
this correlation by consuming the X-Request-Id if one exists, or generating a request id if one does not. It then
provides a context-aware logger that can be invoked throughout the call-stack, appending the request id to the log
message.

It is based on [Winston](https://github.com/winstonjs/winston) and
[express-winston](https://github.com/bithavoc/express-winston) libraries and uses SumoLogic's preferred severity
definitions.

## Usage

### Full example

```ts
import {
  configureAccessLoggingMiddleware,
  loggingContextCreatorMiddleware,
  logger
} from '@skutopia/logger';
import * as express from 'express';

const server = express();

server.use(loggingContextCreatorMiddleware);
server.use(configureAccessLoggingMiddleware({ ignoredRoutes: ['/livez', '/readyz'] }));

const doFunctionCall = () => {
  logger.info('This log will have the request id attached to it');
}

server.get('/', (req, res) => {
  doFunctionCall(); // No work required to attach the request id to nested log calls
  res.send('Hello World!');
});
```

### Express.js access log

`configureAccessLoggingMiddleware` produces access logs from Express.js. This logging middleware must be loaded
**_BEFORE_** the route handler to capture the request-response lifecycle.

```typescript
import { configureAccessLoggingMiddleware } from '@skutopia/logger';
import * as express from 'express';

const app = express();

// The logging middleware goes before the route handler.
app.use(configureAccessLoggingMiddleware({ ignoredRoutes: ['/livez', '/readyz'] }));

app.get('/', (req, res) => {
  res.send('Hello World!');
  // Access logs for this route include the request id.
});

app.listen(3000);
```

### Express.js error log for uncaught exceptions from route handlers

`errorLoggingMiddleware` produces contextualised error logs for uncaught errors in the route handlers from Express.js.
This logging middleware must be loaded **_AFTER_** the route handler and before any custom error handlers which are
directed with `next(err)` at the final stage of the request-response lifecycle.

```typescript
import { errorLoggingMiddleware } from '@skutopia/logger';
import * as express from 'express';

const app = express();

app.use(router);
// The logging middleware goes after the route handler and before the custom error handler.
app.use(errorLoggingMiddleware);
app.use(customErrorHandler);
```

### Logging with context

`loggingContextCreatorMiddleware` provides the context necessary for the context-aware logger. This logging middleware
must be loaded
**_BEFORE_** the route handler.

After the logging middleware is loaded, you can simply use `logger` from the `@skutopia/logger` package to log messages.

To load the middleware,

```typescript
import { loggingContextCreatorMiddleware } from '@skutopia/logger';
import * as express from 'express';

const app = express();

app.use(loggingContextCreatorMiddleware);
app.use(router);
```

To get the context object from the request object and use the logger

```typescript
import { logger } from '@skutopia/logger';

function myHandler(req: express.Request, res: express.Response) {
  logger.info('info message');
  logger.error('error message');
  logger.fatal('fatal message');
}
```

### Logging without context

Always use `logger` even if you do not expect the log to occur during a request. `logger` automatically utilises a
non-contextualised logger when a log context is not available. This ensures that code can be safely refactored and the
context aware logger will adapt accordingly.

```typescript
import { logger } from 'skutopia-logger';

logger.info('info message');
logger.error('error message');
logger.fatal('fatal message');
```

### Pretty print

By default, the output is in JSON format. To print it in a human-readable format, set this environment variable.
This is not recommended for Production

```bash
PRETTY_LOG_FORMAT=true
```

## Contribution

### Test

By default, the test Express.js server listens to port `8080`. You can specify a different port by setting the
environment variable `PORT` with

```shell
PORT=3000 npm run test
```

### Commit guidelines

This repo uses [husky](https://www.npmjs.com/package/husky) and [commitlint](https://commitlint.js.org) to enforce
commit message. Please always use

```shell
npm run commit
```

to submit commit messages.

### Publish guidelines


Go through the release process by doing the following:

```shell
npm run release
```

This will create a release and once merged to the main branch, publish it to NPM public repository.

## API Reference

Please refer to the generated [docs](docs/index.html) for the API reference.
