///|
/// One captured log event with its time. `capture` reads all parts of the event
/// one time, including the `Show` text of its error, so the record cannot change
/// after it is made. Each sink of one session renders the same record.
pub struct LogRecord {
priv timestamp : LogTimestamp
priv level : @logging.Level
priv category : String?
priv template : String
priv message : String
priv segments : Array[@logging.MessageSegment]
priv properties : Array[(String, Json)]
priv error_text : String?
}
///|
/// Capture `event` at `timestamp`. The error text is the `Show` text of the
/// error now, so a later change to a mutable error does not change the record.
pub fn LogRecord::capture(
event : @logging.LogEvent,
timestamp : LogTimestamp,
) -> LogRecord {
{
timestamp,
level: event.level,
category: event.category,
template: event.template,
message: event.message(),
segments: event.segments(),
properties: event.properties(),
error_text: event.error.map(error => "\{error}"),
}
}
///|
/// The time at which the session got the event.
pub fn LogRecord::timestamp(self : LogRecord) -> LogTimestamp {
self.timestamp
}
///|
/// The severity of the event.
pub fn LogRecord::level(self : LogRecord) -> @logging.Level {
self.level
}
///|
/// The category of the event, or `None` when it has no category.
pub fn LogRecord::category(self : LogRecord) -> String? {
self.category
}
///|
/// The message template as the caller wrote it.
pub fn LogRecord::template(self : LogRecord) -> String {
self.template
}
///|
/// The message text, as `LogEvent::message` gave it.
pub fn LogRecord::message(self : LogRecord) -> String {
self.message
}
///|
/// A copy of the message segments. A change to the result, or to a JSON value
/// in it, does not change the record.
pub fn LogRecord::segments(self : LogRecord) -> Array[@logging.MessageSegment] {
self.segments.map(segment => match segment {
Text(_) => segment
Value(name~, value~) => Value(name~, value=copy_json(value))
})
}
///|
/// A copy of the properties in hole order, with each repeated name. A change to
/// the result, or to a JSON value in it, does not change the record.
pub fn LogRecord::properties(self : LogRecord) -> Array[(String, Json)] {
self.properties.map(entry => (entry.0, copy_json(entry.1)))
}
///|
/// The `Show` text of the error at capture, or `None` when the event has no
/// error.
pub fn LogRecord::error_text(self : LogRecord) -> String? {
self.error_text
}
///|
/// A deep copy of `value`: a JSON array or object gets new arrays and maps at each
/// level, so no other code shares them.
fn copy_json(value : Json) -> Json {
match value {
Array(items) => Json::array(items.map(copy_json))
Object(fields) => {
let copy = Map([])
for name, field in fields {
copy[name] = copy_json(field)
}
Json::object(copy)
}
_ => value
}
}