(import logger medea chicken.port chicken.string) (define (capture-log format thunk) (let ((out (open-output-string))) (parameterize ((logger/output out) (logger/format format) (logger/level 'debug) (logger/module-levels '()) (logger/error-hook #f)) (thunk) (get-output-string out)))) (define (capture-json thunk) (with-input-from-string (capture-log 'json thunk) read-json)) (test-group "logger text output" (test-assert "concatenates message parts" (substring-index "user 123 logged in" (capture-log 'text (lambda () (logger/i "user " 123 " logged in"))))) (let ((output (capture-log 'text (lambda () (logger/i "user logged in" '((user-id . 123))))))) (test-assert "prints the message when structured fields are present" (substring-index "user logged in" output)) (test-assert "separates structured fields from message" (substring-index "user logged in ((user-id . 123))" output)) (test-assert "stringifies structured fields" (substring-index "((user-id . 123))" output)))) (test-group "logger JSON output" (let ((entry (capture-json (lambda () (logger/i "user logged in" '((user-id . 123) (ip . "127.0.0.1"))))))) (test "includes level" "info" (alist-ref 'level entry)) (test "includes module" "GLOBAL" (alist-ref 'module entry)) (test "includes message" "user logged in" (alist-ref 'message entry)) (test "includes numeric structured field" 123 (alist-ref 'user-id entry)) (test "includes string structured field" "127.0.0.1" (alist-ref 'ip entry)) (test-assert "includes timestamp" (number? (alist-ref 'ts entry)))) (let ((entry (capture-json (lambda () (logger/i "user " 123 " logged in"))))) (test "keeps variadic message concatenation" "user 123 logged in" (alist-ref 'message entry)) (test "does not add absent structured fields" #f (alist-ref 'user-id entry)))) (test-group "logger error hook" (let ((hook-message #f) (hook-level #f)) (let ((out (open-output-string))) (parameterize ((logger/output out) (logger/format 'text) (logger/level 'debug) (logger/module-levels '()) (logger/error-hook (lambda (message level) (set! hook-message message) (set! hook-level level)))) (logger/w "warning happened" '((request-id . "abc"))))) (test "passes warning hook level" 1 hook-level) (test "omits structured fields from hook message" "[GLOBAL] warning happened" hook-message)))