silk/logger
Typed semantic logging with replaceable stdout and bounded in-memory providers.
When to use
Require Logger when code emits whole semantic messages but should not choose storage or
destination. Provide StdoutLogger at a process edge. Use InMemoryLogger for
deterministic observation and failure tests.
Details
Each invocation carries one LogLevel and one valid UTF-8 message. The service does not add
formatting, newlines, timestamps, or allocation requirements. The stdout provider forwards only
the message bytes; the in-memory provider retains at most eight committed events and 64 message
bytes, and exposes attempted calls separately from successful commits.
Gotchas
Logger failures are typed LogError values and do not guarantee that a message committed.
In-memory accessors require an event index less than length and a valid message-byte index.
Examples
Record and inspect one warning
import silk.effect { Effect }
import silk.logger { Logger }
import silk.logger { LogLevel }
import silk.usize as usize
effect fn program() -> i32
! Logger.LogError {
let mut logger = Logger.inMemoryProvider()
let logged = run Effect.logWarning("cache miss")
|> Effect.provideMut(&mut logger)
if Logger.length(&logger) != usize.ONE {
return 1
}
if Logger.levelAt(&logger, usize.ZERO) != LogLevel.Warning {
return 2
}
return 42
}
effect fn recover(error: Logger.LogError) -> i32 {
return 0
}
pub fn main() -> i32 {
return run Effect.catchAll(program(), recover)
}Import as Logger with import silk.logger.
Public declarations: 14.
LogLevel
pub enum LogLevelOne closed logging severity from Trace through Error.
Trace
Trace = 0Detailed diagnostic events.
Debug
Debug = 1Development diagnostic events.
Info
Info = 2Ordinary operational events.
Warning
Warning = 3Recoverable abnormal conditions.
Error
Error = 4Operations that did not complete as intended.
LogError
pub struct LogErrorA typed failure reported by one Logger provider.
Details
The numeric code belongs to the provider. Portable code can recover from LogError without
assigning one meaning to that code across different providers.
errorCode
pub fn errorCode(error: LogError) -> i32Returns the provider-defined failure code for diagnostics.
Gotchas
Interpret this code only with knowledge of the selected provider. Different providers can use the same code for different failures.
Logger
pub service LoggerA replaceable service that receives one complete semantic log event per call.
When to use
Use this service when library code must emit events without selecting stdout, memory, or another destination.
Details
Each call carries one severity and one valid UTF-8 message. The service does not require a newline, timestamp, prefix, allocation, or output destination. The provider owns those choices.
Operation log
effect fn log(level: LogLevel, message: string) -> () ! LogError ? &mut LoggerSubmits one complete UTF-8 message at one severity to the active provider.
Details
The call preserves the message bytes exactly. It does not add a newline, severity label,
timestamp, or other formatting. A provider failure produces LogError.
StdoutLogger
pub struct StdoutLoggerA Logger provider that writes each complete message to process standard output.
Details
The provider ignores the severity for physical formatting and writes only the UTF-8 message bytes. It adds no newline and performs no message allocation.
stdoutProvider
pub fn stdoutProvider() -> StdoutLoggerCreates a logger that forwards each complete message to process standard output.
Gotchas
The caller must include a newline in message when line separation is required. A standard-
output write failure becomes a provider-defined LogError.
Implementation Logger for StdoutLogger
impl Logger for StdoutLoggerOperation log
log = StdoutLogger.writeStdoutInMemoryLogger
pub struct InMemoryLoggerA deterministic Logger provider that retains up to eight events and 64 total message bytes.
When to use
Use this provider in tests that must inspect event order, severity, message bytes, or failure behavior without process output.
Details
The provider copies each committed message into fixed internal storage. It records attempted calls separately from committed events. Capacity failure and configured failure do not commit an event.
inMemoryProvider
pub fn inMemoryProvider() -> InMemoryLoggerCreates an empty in-memory logger with capacity for eight events and 64 message bytes.
Gotchas
A call fails when eight events are already committed. A call also fails when its bytes exceed the remaining 64-byte total. Neither failure commits the event.
inMemoryProviderFailAt
pub fn inMemoryProviderFailAt(failAt: usize) -> InMemoryLoggerCreates an in-memory logger that rejects one zero-based attempted-call ordinal.
Details
The configured attempt increases attempts but does not increase length or consume
message capacity. Other attempts retain the eight-event and 64-byte limits of
inMemoryProvider.
Implementation Logger for InMemoryLogger
impl Logger for InMemoryLoggerOperation log
log = InMemoryLogger.recordlength
pub fn length(self: &silk/logger.InMemoryLogger) -> usizeReturns the number of events that the in-memory logger committed.
Details
Failed attempts do not increase this count. Use attempts when rejected calls must also be
observed.
levelAt
pub fn levelAt(self: &silk/logger.InMemoryLogger, index: usize) -> LogLevelReturns the severity of one committed event.
Gotchas
index must be less than length. An unused index below eight returns the initial Trace
value instead of trapping. An index of eight or more traps.
messageLengthAt
pub fn messageLengthAt(self: &silk/logger.InMemoryLogger, index: usize) -> usizeReturns the UTF-8 byte length of one committed message.
Gotchas
index must be less than length. An unused index below eight returns zero instead of
trapping. An index of eight or more traps.
messageByteAt
pub fn messageByteAt(self: &silk/logger.InMemoryLogger, eventIndex: usize, byteIndex: usize) -> u8Returns one UTF-8 byte from a committed message.
Gotchas
eventIndex must be less than length. byteIndex must be less than
messageLengthAt for that event. An unused event or invalid byte index traps. An event index
of eight or more also traps.
attempts
pub fn attempts(self: &silk/logger.InMemoryLogger) -> usizeReturns the number of calls attempted, including calls that produced LogError.