BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_recordjsonformatter

Detailed Description

Outline

Purpose

Provide a formatter for log records that renders output in JSON.

Classes

See also
ball_record, ball_recordattributes

Description

This component provides a function object class, ball::RecorJsonFormatter, that formats a log record as JSON text elements according to a format specification (see {Record Format Specification}). ball::RecordJsonFormatter is designed to match the function signature expected by many concrete ball::Observer implementations that publish log records (for example, see ball::FileObserver2::setLogFileFunctor).

NOTE: ball::RecorJsonFormatter renders individual log records as JSON, but, for example, a resulting log file would contain a sequence of JSON strings, which is not itself valid JSON text.

Record Format Specification

A format specification is, itself, a JSON array, supplied to a RecordJsonFormatter object by the setFormat function. If no format is specified, the default format is used. Each array element specifies the format of a log record field or a user-defined attribute. Here is a simple example:

[{"timestamp":{"format":"iso8601"}}, "pid", "tid", "severity", "message"]

would a result in a log record like:

{ "timestamp": "2020-08-28T14:43:50.375Z",
"pid": 2313,
"tid": 12349388604,
"severity": "INFO",
"message": "Hello, world!"
}

Again, the format specification is a JSON array, each element of which can be one of the following:

Field Format Specification

The following table lists the predefined string values for each fixed field and user-defined attributes in the log record:

Tag Description Example
-------------- ------------------------- -------------
"timestamp" creation date and time ["timestamp"]
"pid" process id of creator ["pid"]
"tid" thread id of creator ["tid"]
"file" file where created (__FILE__) ["file"]
"line" line number in file (__LINE__) ["line"]
"category" category of logged record ["category"]
"severity" severity of logged record ["severity"]
"message" log message text ["message"]
"attributes" all user-defined attributes ["attributes"]
<attribute name> specific user-defined attribute ["bas.uuid"]

The output format of each field can be customized by replacing a string value in the JSON array with a JSON object having the same name and a set of key-value pairs (attributes).

Verifying the Format Specification for setFormat

The sections that follow describe the set of fields that can be provided in the format specification supplied to setFormat. RecordJsonFormatter::setFormat will ignore fields in the provided format specification that are unknown, but will report an error if a known field contains a property that is not supported. For example: a format specification '["pid", { "timestamp" : {"unknown field!": "value"} }] will be accepted, but ["pid", {"timestamp": {"format": "unknown format" }}] will produce an error.

Each key-value pair of a JSON object that specifies a format of an output of a fixed record field or a user-defined attribute has the following constrains:

The "timestamp" field format

The format attributes of the "timestamp" object are given in the following table:

Value Default
Key Description Constraint Value
------------------------ ---------------- ----------- ------------
"name" name by which JSON string "timestamp"
"timestamp" will
be published
"format" datetime format "iso8601", "iso8601"
"bdePrint"
(*Note*)
"fractionalSecPrecision" second precision "none", "microseconds"
"milliseconds",
"microseconds"
"timeZone" time zone "utc", "utc"
"local"

Note: The default "bdePrint" format denotes the following datetime format:

DDMonYYYY_HH:MM:SS.mmm

For example, the following record format specification:

[ { "timestamp": { "name": "Time",
"fractionalSecPrecision": "microseconds",
"timeZone": "local" } }
]

would a result in a log record like:

{ "Time": "28AUG2020_17:43:50.375345" }

The "pid" (process Id) field format

The format attributes of the process Id field are given in the following table:

Value Default
Key Description Constraint Value
------ ------------------------------------- ----------- -------
"name" name by which "pid" will be published JSON string "pid"

For example, the following record format specification:

[ { "pid": { "name": "Process Id" } } ]

would a result in a log record like:

{ "Process Id": 2313 }

The "tid" (thread Id) field format

The format attributes of the thread Id field are given in the following table:

Value Default
Key Description Constraint Value
-------- ------------------------------------- ----------- ---------
"name" name by which "tid" will be published JSON string "tid"
"format" output format "decimal", "decimal"
"hex"

For example, the following record format specification:

[ { "tid": { "name": "Thread Id",
"format": "hex" } }
]

would a result in a log record like:

{ "Thread Id": 0xA7654EFF3540 }

The "file" field format

The format attributes of the "file" field are given in the following table:

Default
Key Description Value Constraint Value
------ -------------------- ----------------------------- -------
"name" name by which "file" JSON string "file"
will be published
"path" file path "full" (__FILE__), "full"
"file" (basename of __FILE__)

For example, the following record format specification:

[ { "file": { "name": "File",
"path": "file" } }
]

would a result in a log record like:

{ "File": "test.cpp" }

The "line" field format

The format attributes of the "line" field are given in the following table:

Value Default
Key Description Constraint Value
------ --------------------------------------- ----------- -------
"name" name by which "line" will be published JSON string "line"

For example, the following record format specification:

[ { "line": { "name": "Line" } } ]

would a result in a log record like:

{ "Line": 512 }

The "category" field format

The format attributes of the "category" field are given in the following table:

Value Default
Key Description Constraint Value
------ ------------------------------------------ ----------- ----------
"name" name by which "category" will be published JSON string "category"

For example, the following record format specification:

[ { "category": { "name": "Category" } } ]

would a result in a log record like:

{ "category": "Server" }

The "severity" field format

The format attributes of the "severity" field are given in the following table:

Value Default
Key Description Constraint Value
------ ------------------------------------------ ----------- ----------
"name" name by which "severity" will be published JSON string "severity"

For example, the following record format specification:

[ { "severity": { "name": "severity" } } ]

would a result in a log record like:

{ "Severity": "ERROR" }

The "message" field format

A message is a JSON string which is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes: (", \, \/, , \f,
, \r, \t, \u{4 hex digits}).

The format attributes of the "message" field are given in the following table:

Value Default
Key Description Constraint Value
------ ----------------------------------------- ----------- ---------
"name" name by which "message" will be published JSON string "message"

For example, the following record format specification:

[ { "message": { "name": "msg" } } ]

would a result in a log record like:

{ "msg": "Log message" }

The "attributes" format

The "attributes" JSON object has no attributes. For example, the following record format specification:

[ "attributes" ]

would (assuming their are two attributes "bas.requestid" and "mylib.security") result in a log record like:

{ "bas.requestid": 12345, "mylib.security": "My Security" }

A user-defined attribute format

Each user-defined attribute has a single "name" attribute that can be used to rename the user-defined attribute:

Value Default
Key Description Constraint Value
------ ---------------------------- ----------- -------
"name" name by which a user-defined JSON string none
attribute will be published

For example, the following record format specification:

[ { "bas.uuid": { "name": "BAS.UUID" } } ]

would a result in a log record like:

{ "BAS.UUID": 3593 }

The Record Separator

The record separator is a string that is printed after each formatted record. The default value of the record separator is a single newline, but it can be set to any string of the user's choice using the RecordJsonFormatter::setRecordSeparator function.

Usage

This section illustrates intended use of this component.

Example: Format log records as JSON and render them to stdout

Suppose an application needs to format log records as JSON and output them to stdout.

First we instantiate a JSON record formatter:

Definition ball_recordjsonformatter.h:492

Next we set a format specification to the newly created formatter:

int rc = formatter.setFormat("[\"tid\",\"message\"]");
assert(0 == rc); (void)rc;
int setFormat(const bsl::string_view &format)

The chosen format specification indicates that, when a record is formatted using formatter, the thread Id attribute of the record will be output followed by the message attribute of the record.

Then we create a default ball::Record and set the thread Id and message attributes of the record to dummy values:

ball::Record record;
record.fixedFields().setMessage("Hello, World!");
void setThreadID(bsls::Types::Uint64 threadID)
Definition ball_recordattributes.h:574
void setMessage(const char *message)
Definition ball_record.h:178
RecordAttributes & fixedFields()
Return the modifiable fixed fields of this log record.
Definition ball_record.h:396

Next, invocation of the formatter function object to format record to bsl::cout:

formatter(bsl::cout, record);

yields this output, which is terminated by a single newline:

{"tid":6,"message":"Hello, World!"}

Finally, we change the record separator and format the same record again:

formatter.setFormat("\n\n");
formatter(bsl::cout, record);

The record is printed in the same format, but now terminated by two newlines:

{"tid":6,"message":"Hello, World!"}