LogFormats

About

This class provides static functions useful for formatting log messages. It implements the following winston formatsopen in new window:

colorize
combine
errors
json
label
metadata
padLevels
printf (alias: format)
timestamp
uncolorize

Creating custom formats

Formats are objects that have a .transform() function property with the following signature:

.transform(info: Object; options: Object) : Object

  • info — an object representing the log message.
  • options — settings specific to the current format.

The function is expected to return one of two things:

  • An info object representing the modified info parameter. You may mutate and return the info parameter.
  • A falsey value (_.falsey() is true) indicating that the info parameter should be ignored by the caller. See Filtering info Objects below.

To create a format, use the .createFormat() function.

info objects

The info parameter provided to .transform() represents a single log message. The object itself is mutable. Every info object must have at least .level and .message properties:

var $info : Object

$info:=New object()
$info.level:="info"  // Level of the logged message
$info.message:="Hey! Log something!"  // Message being logged

Properties besides .level and .message are considered metadata:

var $info : Object

$info:=New object()
$info.level:="info"  // Level of the logged message
$info.message:="Hey! Log something!"  // Message being logged
$info.foo:="bar"  // Metadata

Several of the formats in LogFormats add additional properties:

PropertyAdded byDescription
.timestamptimestamp()Timestamp at which the message was received
.labellabel()Custom label associated with each message

Your .transform() function may add whatever properties you wish to info, but those properties should not begin with an underscore ("_").

NOTE

All properties beginning with an underscore should be considered private and read only.

Combining formats

Any number of formats may be combined into a single format using .combine(). Since .combine() takes no options, as a convenience it returns a pre-created instance of the combined format.

Filtering info objects

If you wish to filter out a given info object completely then simply return a falsey value. For an example, see .createFormat().

API

.colorize()

.colorize({ options : Object }) : Object

This format adds different colors to the message and/or level, depending on the log level. It accepts the following properties in options:

PropertyDescription
.levelIf truthy the color will be applied to info.level
.messageIf truthy the color will be applied to info.message
.allIf truthy the color will be applied to info.message and info.level
.colorsAn object containing colors for log levels

If neither .level, .all, nor .message are specified, the level will be colorized by default.

Example

var $colorize; $colors; $options : Object

$colors:=New object("info"; "blue"; "error"; "bgRed.white")
$options:=New object("level"; True; "colors"; $colors)
$colorize:=Logger.formats.colorize($options)

.combine()

.combine(format : Object { …formatN : Object }) : Object

This format allows you to combine multiple formats into one, which is necessary if you want to use more than one format with a logger.

Each format should be an object created with the .createFormat() function. The formats are applied in the order they are passed. If a format returns a falsey value (_.falsey() is true), the remaining formats are not applied.

Example

var $format : Object
var $logFormat : Text

$logFormat:="${timestamp} ${level}: ${message} ${metadata}"
$format:=Logger.format.combine(\
  Logger.formats.timestamp(New object("format"; "YYYY-MM-DD HH:mm:ss")); \
  Logger.formats.colorize(); \
  Logger.formats.format(Formula(_.format($logFormat; $1)))\
  )

$logger.configure(New object(\
  "transports"; New collection($transport); \
  "format"; $format)\
  )

.createFormat()

.createFormat(thisObj : Object; transformFunction : Text { ; options : Object }) : Object

Creates a format that will call:

thisObj[transformFunction].call(thisObj; info; options)

Within the transform function, This will be thisObj.

Example

Let’s say we want to create a format that filters out log messages with a given level. Here’s one way it can be accomplished.

var $format; $config; $filter : Object
var $logger : cs.js.Logger

// When the formula is called, $1 will be the info object
// and $2 will be the options object. Returning a falsey
// value from a formatter will cause that log message to be discarded.
$format:=New object("filter"; Formula(($1.level=$2.level) ? False : $1))

// $2.level above will be "error"
$filter:=Logger.formats.createFormat(\
  $format; \
  "filter"; \
  New object("level"; "error")\
  )

// Create a logger with the filter format
$transport:=cs.js.Transport.new(\
  "console"; \
  cs.ConsoleTransport; \
  New object("format"; $filter)\
  )
$config:=New object("transports"; New collection($transport))
$logger:=Logger.create("filteredLogger"; $config)

$logger.info("test")    // This will be logged
$logger.error("error")  // This will not be logged
$logger.warn("warn")    // This will be logged

.errors()

.errors({ options : Object }) : Object

This format allows you to pass instances of Error as the log message to one of the logging functions. The Error’s .message property will be set as the log message, and if options.stack is truthy, the Error’s stack trace will be added to the log message.


.format()

.format(options : Object) : Object

By default, Logger formats log messages as a stringified JSON object. That is usually not what you want. To show anything meaningful in the log, you have to tell Logger what you want to log and how to display it. This function allows you to specify that.

If options is a Callable, it is called with the info as its only parameter and the result is set as the log message.

If options has a .template text property, _.format($options.template; $info) is called and the result is set as the log message.

Examples

// These are equivalent
$format:=Logger.formats.combine(\
  Logger.formats.timestamp(); \
  Logger.formats.format(Formula(_.format("${timestamp} ${message}"; $1))))

$format:=Logger.formats.combine(\
  Logger.formats.timestamp(); \
  Logger.formats.format(New object("template"; "${timestamp} ${message}")))

.json()

.json({ options : Object }) : Object

This format sets the log message to the result of calling _.stringify($info). You may control the formatting of the stringification by setting .pretty and/or .indent properties on options, which correspond to the same parameters of the .stringify() function.


.label()

.label(options : Object) : Object

This format adds the text options.label to log messages. If options.message is truthy, the log message is set to: [<options.label>] <message>. Otherwise info.label is set to options.label and it is up to you to use info.label, typically via the .format() format.

Examples

$format:=Logger.formats.label(New object("label"; "myApp"; "message"; True))
console.format:=$format
console.info("This is a test")
// "[myApp] This is a test"

$label:=Logger.formats.label(New object("label"; "myApp"))
$format:=Logger.formats.combine(\
  $label; \
  Logger.formats.format(New object("template"; "${label}: ${message}")))
console.format:=$format
console.info("This is a test")
// "myApp: This is a test"

.metadata()

.metadata({ options : Object }) : Object

This format adds a metadata object to info. It accepts the following options:

OptionDescription
keyThe key to use for the metadata object. Defaults to "metadata".
fillExceptA collection of info keys to exclude from the metadata object.
fillWithA collection of info keys to include in the metadata object.

Example

$options:=New object(\
  "key"; "meta"; \
  "fillExcept"; New collection("foo"))

$format:=Logger.formats.metadata($options)
$info:=New object(\
  "level"; "info"; \
  "message"; "A test"; \
  "count"; 27; \
  "foo"; "homer"; \
  "bar"; "marge")
$info:=$format.transform($format.this; $info; $format.options)

// $info
{
  "foo": "homer",
  "level": "info",
  "message": "A test",
  "meta": {
    "count": 27,
    "bar": "marge"
  }
}

.padLevels()

.padLevels({ options : Object }) : Object

This format pads level names to be the same length. By default, padding is done with a space character. To use a different filler, pass it in options.filler.

NOTE

If you are combining .colorize() with this format, be sure to list this format first.

Examples

// Log entries without padLevels()
error: Something went wrong
warn: Pay attention
info: Hello world
verbose: I'm chatty
debug: bug bug bug

// Log entries with padLevels()
error  : Something went wrong
warn   : Pay attention
info   : Hello world
verbose: I'm chatty
debug  : bug bug bug

.printf()

.printf(options : Object) : Object

This format is an alias for the .format() function.


.timestamp()

.timestamp({ options : Object }) : Object

This format adds a .timestamp property to info. The value of the .timestamp property is determined by options:

  • If options.format is a function, it is called with three parameters: Current date, Current time, and the current milliseconds as an integer. The function should return a string.
  • If options.format is a string, it is passed to DateTime.format().
  • If options.format is not set, the .timestamp property is set to 4D’s Timestampopen in new window.

If you would like to set a property to the timestamp in addition to info.timestamp, pass the property name in options.alias.


.uncolorize()

.uncolorize({ options : Object }) : Object

This format strips ANSI colors from info. What gets stripped depends on options:

  • If options.level is false, the level is not stripped.
  • If options.message is false, the message is not stripped.
Last Updated:
Contributors: Aparajita