# Layouts

Layouts are functions used by appenders to format log events for output. They take a log event as an argument and return a string. Log4js comes with several appenders built-in, and provides ways to create your own if these are not suitable.

For most use cases you will not need to configure layouts - there are some appenders which do not need layouts defined (for example, [logFaces-UDP](https://github.com/log4js-node/logFaces-UDP)); all the appenders that use layouts will have a sensible default defined.

## Configuration

Most appender configuration will take a field called `layout`, which is an object - typically with a single field `type` which is the name of a layout defined below. Some layouts require extra configuration options, which should be included in the same object.

## Example

```javascript
log4js.configure({
  appenders: { out: { type: "stdout", layout: { type: "basic" } } },
  categories: { default: { appenders: ["out"], level: "info" } },
});
```

This configuration replaces the [stdout](stdout.md) appender's default `coloured` layout with `basic` layout.

# Built-in Layouts

## Basic

- `type` - `basic`

Basic layout will output the timestamp, level, category, followed by the formatted log event data.

## Example

```javascript
log4js.configure({
  appenders: { out: { type: "stdout", layout: { type: "basic" } } },
  categories: { default: { appenders: ["out"], level: "info" } },
});
const logger = log4js.getLogger("cheese");
logger.error("Cheese is too ripe!");
```

This will output:

```
[2017-03-30 07:57:00.113] [ERROR] cheese - Cheese is too ripe!
```

## Coloured

- `type` - `coloured` (or `colored`)

This layout is the same as `basic`, except that the timestamp, level and category will be coloured according to the log event's level (if your terminal/file supports it - if you see some weird characters in your output and no colour then you should probably switch to `basic`). The colours used are:

- `TRACE` - 'blue'
- `DEBUG` - 'cyan'
- `INFO` - 'green'
- `WARN` - 'yellow'
- `ERROR` - 'red'
- `FATAL` - 'magenta'

## Message Pass-Through

- `type` - `messagePassThrough`

This layout just formats the log event data, and does not output a timestamp, level or category. It is typically used in appenders that serialise the events using a specific format (e.g. [gelf](https://github.com/log4js-node/gelf)).

## Example

```javascript
log4js.configure({
  appenders: {
    out: { type: "stdout", layout: { type: "messagePassThrough" } },
  },
  categories: { default: { appenders: ["out"], level: "info" } },
});
const logger = log4js.getLogger("cheese");
const cheeseName = "gouda";
logger.error("Cheese is too ripe! Cheese was: ", cheeseName);
```

This will output:

```
Cheese is too ripe! Cheese was: gouda
```

## Dummy

- `type` - `dummy`

This layout only outputs the first value in the log event's data. It was added for the [logstashUDP](https://github.com/log4js-node/logstashUDP) appender, and I'm not sure there's much use for it outside that.

## Example

```javascript
log4js.configure({
  appenders: { out: { type: "stdout", layout: { type: "dummy" } } },
  categories: { default: { appenders: ["out"], level: "info" } },
});
const logger = log4js.getLogger("cheese");
const cheeseName = "gouda";
logger.error("Cheese is too ripe! Cheese was: ", cheeseName);
```

This will output:

```
Cheese is too ripe! Cheese was:
```

## Pattern

- `type` - `pattern`
- `pattern` - `string` - specifier for the output format, using placeholders as described below
- `tokens` - `object` (optional) - user-defined tokens to be used in the pattern

## Pattern format

The pattern string can contain any characters, but sequences beginning with `%` will be replaced with values taken from the log event, and other environmental values.
Format for specifiers is `%[padding].[truncation][field]{[format]}` - padding and truncation are optional, and format only applies to a few tokens (notably, date). Both padding and truncation values can be negative.

- Positive truncation - truncate the string starting from the beginning
- Negative truncation - truncate the string starting from the end of the string
- Positive padding - left pad the string to make it this length, if the string is longer than the padding value then nothing happens
- Negative padding - right pad the string to make it this length, if the string is longer than the padding value then nothing happens
  To make fixed-width columns in your log output, set padding and truncation to the same size (they don't have to have the same sign though, you could have right truncated, left padded columns that are always 10 characters wide with a pattern like "%10.-10m").

e.g. %5.10p - left pad the log level by up to 5 characters, keep the whole string to a max length of 10.
So, for a log level of INFO the output would be " INFO", for DEBUG it would be "DEBUG" and for a (custom) log level of CATASTROPHIC it would be "CATASTROPH".

Fields can be any of:

- `%r` time in toLocaleTimeString format
- `%p` log level
- `%c` log category
- `%h` hostname
- `%m` log data
- `%m{l}` where l is an integer, log data.slice(l)
- `%m{l,u}` where l and u are integers, log data.slice(l, u)
- `%d` date, formatted - default is `ISO8601`, format options are: `ISO8601`, `ISO8601_WITH_TZ_OFFSET`, `ABSOLUTETIME`, `DATETIME`, or any string compatible with the [date-format](https://www.npmjs.com/package/date-format) library. e.g. `%d{DATETIME}`, `%d{yyyy/MM/dd-hh.mm.ss}`
- `%%` % - for when you want a literal `%` in your output
- `%n` newline
- `%z` process id (from `process.pid`)
- `%f` full path of filename (requires `enableCallStack: true` on the category, see [configuration object](api.md))
- `%f{depth}` path's depth let you chose to have only filename (`%f{1}`) or a chosen number of directories
- `%l` line number (requires `enableCallStack: true` on the category, see [configuration object](api.md))
- `%o` column position (requires `enableCallStack: true` on the category, see [configuration object](api.md))
- `%s` call stack (requires `enableCallStack: true` on the category, see [configuration object](api.md))
- `%C` class name (requires `enableCallStack: true` on the category, see [configuration object](api.md) and [#1316](https://github.com/log4js-node/log4js-node/pull/1316))
- `%M` method or function name (requires `enableCallStack: true` on the category, see [configuration object](api.md) and [#1316](https://github.com/log4js-node/log4js-node/pull/1316))
- `%A` method or function alias (requires `enableCallStack: true` on the category, see [configuration object](api.md) and [#1316](https://github.com/log4js-node/log4js-node/pull/1316))
- `%F` fully qualified caller name (requires `enableCallStack: true` on the category, see [configuration object](api.md) and [#1316](https://github.com/log4js-node/log4js-node/pull/1316))
- `%x{<tokenname>}` add dynamic tokens to your log. Tokens are specified in the tokens parameter.
- `%X{<tokenname>}` add values from the Logger context. Tokens are keys into the context values.
- `%[` start a coloured block (colour will be taken from the log level, similar to `colouredLayout`)
- `%]` end a coloured block

## Tokens

User-defined tokens can be either a string or a function. Functions will be passed the log event, and should return a string. For example, you could define a custom token that outputs the log event's context value for 'user' like so:

```javascript
log4js.configure({
  appenders: {
    out: {
      type: "stdout",
      layout: {
        type: "pattern",
        pattern: "%d %p %c %x{user} %m%n",
        tokens: {
          user: function (logEvent) {
            return AuthLibrary.currentUser();
          },
        },
      },
    },
  },
  categories: { default: { appenders: ["out"], level: "info" } },
});
const logger = log4js.getLogger();
logger.info("doing something.");
```

This would output:

```
2017-06-01 08:32:56.283 INFO default charlie doing something.
```

You can also use the Logger context to store tokens (sometimes called Nested Diagnostic Context, or Mapped Diagnostic Context) and use them in your layouts.

```javascript
log4js.configure({
  appenders: {
    out: {
      type: "stdout",
      layout: {
        type: "pattern",
        pattern: "%d %p %c %X{user} %m%n",
      },
    },
  },
  categories: { default: { appenders: ["out"], level: "info" } },
});
const logger = log4js.getLogger();
logger.addContext("user", "charlie");
logger.info("doing something.");
```

This would output:

```
2017-06-01 08:32:56.283 INFO default charlie doing something.
```

Note that you can also add functions to the Logger Context, and they will be passed the logEvent as well.

# Adding your own layouts

You can add your own layouts by calling `log4js.addLayout(type, fn)` before calling `log4js.configure`. `type` is the label you want to use to refer to your layout in appender configuration. `fn` is a function that takes a single object argument, which will contain the configuration for the layout instance, and returns a layout function. A layout function takes a log event argument and returns a string (usually, although you could return anything as long as the appender knows what to do with it).

## Custom Layout Example

This example can also be found in examples/custom-layout.js.

```javascript
const log4js = require("log4js");

log4js.addLayout("json", function (config) {
  return function (logEvent) {
    return JSON.stringify(logEvent) + config.separator;
  };
});

log4js.configure({
  appenders: {
    out: { type: "stdout", layout: { type: "json", separator: "," } },
  },
  categories: {
    default: { appenders: ["out"], level: "info" },
  },
});

const logger = log4js.getLogger("json-test");
logger.info("this is just a test");
logger.error("of a custom appender");
logger.warn("that outputs json");
log4js.shutdown(() => {});
```

This example outputs the following:

```javascript
{"startTime":"2017-06-05T22:23:08.479Z","categoryName":"json-test","data":["this is just a test"],"level":{"level":20000,"levelStr":"INFO"},"context":{}},
{"startTime":"2017-06-05T22:23:08.483Z","categoryName":"json-test","data":["of a custom appender"],"level":{"level":40000,"levelStr":"ERROR"},"context":{}},
{"startTime":"2017-06-05T22:23:08.483Z","categoryName":"json-test","data":["that outputs json"],"level":{"level":30000,"levelStr":"WARN"},"context":{}},
```
