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
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 Filteringinfo
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:
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.
info
objects
Filtering 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.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 toDateTime.format()
. - If
options.format
is not set, the.timestamp
property 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.level
is false, the level is not stripped. - If
options.message
is false, the message is not stripped.