LogFormats
About
This class provides static functions useful for formatting log messages. It implements the following winston formats:
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
infoobject 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 FilteringinfoObjects 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:
| Property | Added by | Description |
|---|---|---|
| .timestamp | timestamp() | Timestamp at which the message was received |
| .label | label() | 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:
| Property | Description |
|---|---|
| .level | If truthy the color will be applied to info.level |
| .message | If truthy the color will be applied to info.message |
| .all | If truthy the color will be applied to info.message and info.level |
| .colors | An 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:
| Option | Description |
|---|---|
| key | The key to use for the metadata object. Defaults to "metadata". |
| fillExcept | A collection of info keys to exclude from the metadata object. |
| fillWith | A 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.formatis 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.formatis a string, it is passed toDateTime.format(). - If
options.formatis not set, the.timestampproperty is set to 4D’sTimestamp.
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.levelis false, the level is not stripped. - If
options.messageis false, the message is not stripped.