viva_telemetry/log
viva_telemetry/log - Structured logging for Gleam
Inspired by: structlog (Python), zap (Go), tracing (Rust)
Features
- Structured logging with key-value fields
- Multiple handlers (console, file, JSON)
- Log levels (RFC 5424)
- Context propagation
- Sampling for high-volume logs
Quick Start
import viva_telemetry/log
pub fn main() {
// Simple logging
log.info("Server started", [#("port", "8080")])
// With context
log.with_context([#("request_id", "abc123")], fn() {
log.debug("Processing request", [])
})
}
Values
pub fn add_handler(handler: handler.Handler) -> Nil
Add a handler to the existing configuration
pub fn alert(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at alert level
pub fn alert_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy alert
pub fn bind_context(context: List(#(String, String))) -> Nil
Add context fields that persist for this process
pub fn configure_console(lvl: level.Level) -> Nil
Quick setup: console handler with specified level
Example:
log.configure_console(log.debug_level)
pub fn configure_full(
console_level: level.Level,
json_path: String,
json_level: level.Level,
) -> Nil
Quick setup: console + JSON file
Example:
log.configure_full(log.debug_level, "app.jsonl", log.info_level)
pub fn configure_json(path: String, lvl: level.Level) -> Nil
Quick setup: JSON file handler with specified level
Example:
log.configure_json("app.jsonl", log.info_level)
pub fn critical(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at critical level
pub fn critical_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy critical
pub fn debug(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at debug level
pub fn debug_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy debug - most common use case for lazy logging
Example:
// String only constructed if debug level is enabled
log.debug_lazy(fn() { "Item: " <> int.to_string(i) }, [])
pub fn emergency(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at emergency level
pub fn emergency_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy emergency
pub fn error(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at error level
pub fn error_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy error
pub fn info_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy info
pub fn log(
lvl: level.Level,
message: String,
fields: List(#(String, String)),
) -> Nil
Log with explicit level
pub fn log_from(
source: String,
lvl: level.Level,
message: String,
fields: List(#(String, String)),
) -> Nil
Log with source module
pub fn log_lazy(
lvl: level.Level,
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy log - only evaluates message function if log will be emitted
Example:
log.debug_lazy(fn() { "Processing " <> expensive_to_string(data) }, [])
pub fn log_lazy_all(
lvl: level.Level,
message_fn: fn() -> String,
fields_fn: fn() -> List(#(String, String)),
) -> Nil
Lazy log with lazy fields - both message and fields evaluated only if needed
pub fn notice(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at notice level
pub fn notice_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy notice
pub fn sampled(
lvl: level.Level,
rate: Float,
message: String,
fields: List(#(String, String)),
) -> Nil
Log with sampling (only log rate% of messages)
pub fn trace(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at trace level
pub fn trace_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy trace - for high-frequency logs that should be cheap when disabled
pub fn warning(
message: String,
fields: List(#(String, String)),
) -> Nil
Log at warning level
pub fn warning_lazy(
message_fn: fn() -> String,
fields: List(#(String, String)),
) -> Nil
Lazy warning
pub fn with_context(
context: List(#(String, String)),
f: fn() -> a,
) -> a
Execute function with additional context
pub fn would_log(lvl: level.Level) -> Bool
Check if any handler would log at this level Use this to avoid expensive computations when log won’t be emitted