///|
pub(all) struct ConsoleAppender {
use_json : Bool
}
///|
pub fn ConsoleAppender::new() -> ConsoleAppender {
ConsoleAppender::{ use_json: false }
}
///|
pub fn ConsoleAppender::json(_self : ConsoleAppender) -> ConsoleAppender {
ConsoleAppender::{ use_json: true }
}
///|
pub fn ConsoleAppender::append(
self : ConsoleAppender,
record : LogRecord,
) -> String {
if self.use_json {
format_json(record)
} else {
format_text(record)
}
}
///|
pub(all) struct MemoryAppender {
records : Array[String]
entries : Array[LogRecord]
}
///|
pub fn MemoryAppender::new() -> MemoryAppender {
MemoryAppender::{ records: [], entries: [] }
}
///|
pub fn MemoryAppender::append(
self : MemoryAppender,
record : LogRecord,
) -> MemoryAppender {
let new_records = self.records.copy()
new_records.push(format_text(record))
let new_entries = self.entries.copy()
new_entries.push(record.copy())
MemoryAppender::{ records: new_records, entries: new_entries }
}
///|
pub fn MemoryAppender::get_logs(self : MemoryAppender) -> Array[String] {
self.records.copy()
}
///|
pub fn MemoryAppender::get_records(self : MemoryAppender) -> Array[LogRecord] {
copy_records(self.entries, 0, [])
}
///|
pub fn MemoryAppender::count(self : MemoryAppender) -> Int {
self.records.length()
}
// Rolling Appender — keeps only the last N records
///|
pub(all) struct RollingAppender {
records : Array[String]
entries : Array[LogRecord]
max_count : Int
dropped_count : Int
}
///|
pub fn RollingAppender::new(max_count : Int) -> RollingAppender {
let capacity = if max_count < 0 { 0 } else { max_count }
RollingAppender::{
records: [],
entries: [],
max_count: capacity,
dropped_count: 0,
}
}
///|
pub fn RollingAppender::append(
self : RollingAppender,
record : LogRecord,
) -> RollingAppender {
let appended_logs = self.records.copy()
appended_logs.push(format_text(record))
let appended_entries = self.entries.copy()
appended_entries.push(record.copy())
let discarded = if appended_logs.length() > self.max_count {
appended_logs.length() - self.max_count
} else {
0
}
RollingAppender::{
records: keep_last_logs(appended_logs, self.max_count),
entries: keep_last_records(appended_entries, self.max_count),
max_count: self.max_count,
dropped_count: self.dropped_count + discarded,
}
}
///|
fn keep_last_logs(logs : Array[String], max_count : Int) -> Array[String] {
if max_count <= 0 {
[]
} else {
let start = if logs.length() > max_count {
logs.length() - max_count
} else {
0
}
copy_logs(logs, start, [])
}
}
///|
fn copy_logs(
src : Array[String],
idx : Int,
acc : Array[String],
) -> Array[String] {
if idx >= src.length() {
acc
} else {
acc.push(src[idx])
copy_logs(src, idx + 1, acc)
}
}
///|
fn keep_last_records(
records : Array[LogRecord],
max_count : Int,
) -> Array[LogRecord] {
if max_count <= 0 {
[]
} else {
let start = if records.length() > max_count {
records.length() - max_count
} else {
0
}
copy_records(records, start, [])
}
}
///|
fn copy_records(
src : Array[LogRecord],
idx : Int,
acc : Array[LogRecord],
) -> Array[LogRecord] {
if idx >= src.length() {
acc
} else {
acc.push(src[idx].copy())
copy_records(src, idx + 1, acc)
}
}
///|
pub fn RollingAppender::get_logs(self : RollingAppender) -> Array[String] {
self.records.copy()
}
///|
pub fn RollingAppender::get_records(self : RollingAppender) -> Array[LogRecord] {
copy_records(self.entries, 0, [])
}
///|
pub fn RollingAppender::count(self : RollingAppender) -> Int {
self.records.length()
}
///|
pub fn RollingAppender::capacity(self : RollingAppender) -> Int {
self.max_count
}
///|
pub fn RollingAppender::dropped(self : RollingAppender) -> Int {
self.dropped_count
}
///|
pub fn RollingAppender::is_full(self : RollingAppender) -> Bool {
self.max_count > 0 && self.records.length() == self.max_count
}
///|
pub fn RollingAppender::clear(self : RollingAppender) -> RollingAppender {
RollingAppender::{
records: [],
entries: [],
max_count: self.max_count,
dropped_count: 0,
}
}