Конфигурация и наблюдаемость
Типизированная конфигурация#
Задача. Параметры программы — порт, имя, режим отладки — с значениями по умолчанию, профилями и переопределением снаружи.
config App {
port: u16 = 8080
name: str = "demo"
debug: bool = false
profile dev { debug = true } // профиль dev включён по умолчанию
profile prod { port = 443 }
}
fn main() io {
let app = App.get() // значение фиксируется на время работы
print("{app.name} listens on {app.port}, debug={app.debug}")
}Вывод
demo listens on 8080, debug=true
config App { … }— типизированный конфиг: поля как уdata, значения по умолчанию, блокиprofile.App.get()возвращает неизменяемое значение, зафиксированное на всё время работы.- Источники по убыванию приоритета: флаг
--set App.port=8080→ переменная окруженияAPP_PORT→ файлconfig/<профиль>.toml→ блокprofile→ значение по умолчанию. Попробуйте:APP_PORT=9000 oxl run prog.oxlилиoxl run prog.oxl --profile prod. - Неверный тип или нарушенное уточнение (
port: Portс диапазоном) — сообщение с указанием источника и выход с кодом 78 до запуска программы: некорректная конфигурация не доживает до первого запроса. - Секреты объявляют типом
secret<str>: они не попадают в логи и не сериализуются. - Значения, которые нужно менять без перезапуска (лимиты, флаги), описывает
dynamic(§14.2).
Логи, метрики, спаны#
Задача. Записывать события, считать запросы и измерять участки кода.
use std.obs { log, Level, metric, span }
fn handle(id: i64) -> i64 io {
log.info("handling request {id}") // записи идут в stderr, не в stdout
id * 2
}
fn main() io {
log.setLevel(Level.Info)
let served = metric.counter("requests_total", "requests served")
let inflight = metric.gauge("inflight", "requests in flight")
var total = 0
for id in 1..=3 {
inflight.inc()
total += span.with("handle", () => handle(id)) // span измеряет участок и попадает в трассу
served.inc()
inflight.dec()
}
log.debug("not printed: level is Info")
print("total {total}, served {served.value()}, in flight {inflight.value()}")
print("debug enabled: {log.enabled(Level.Debug)}")
}Вывод
total 12, served 3.0, in flight 0.0 debug enabled: false
log.info("…")пишет запись в stderr (вstdoutостаётся только вывод программы); уровень задаётlog.setLevel(Level.Info), флаг запуска--log-level. Записи содержат время, уровень и поля;log.setJson(true)включает формат JSON для сборщиков логов.metric.counter("requests_total", "…"),gauge,histogram— метрики узла; в кластере их показываетoxl inspect.span.with("handle", () => …)измеряет участок и вкладывается в трассу запроса; в сервисах трасса пробрасывается между узлами автоматически (traceIdвctx).- Если сообщение дорого строить, сначала проверьте
log.enabled(Level.Debug).
Вернуться: кулинарная книга.