#lang scheme/base
(require (planet bzlib/base)
"base.ss")
(define (log-event out sec args)
(display (format "~s\n" (cons sec args)) out)
(flush-output out))
(define (log-trace out sec args)
(display (format "~a\n" (car args)) out)
(flush-output out))
(define (log-dispatcher (args (thread-receive)))
(if (not (car args))
(apply log-event (cdr args))
(apply log-trace (cdr args)))
(log-dispatcher))
(define-struct *log (path out thread)
#:property prop:output-port 1
#:property prop:procedure
(lambda ($struct #:trace? (trace? #f) . args)
(thread-cast* (*log-thread $struct) trace? (*log-out $struct) (current-seconds) args)))
(define log-registry (make-immutable-hash-registry))
(define (make-log (log-path #f))
(let ((out (cond ((output-port? log-path) log-path)
((or (string? log-path) (path? log-path))
(open-output-file log-path #:exists 'append))
(else
(case log-path
((cout) (current-output-port))
((cerr) (current-error-port))
(else
(open-output-bytes)))))))
(make-*log log-path out (thread log-dispatcher))))
(define current-log (make-parameter (make-log 'cerr)))
(define (log-trace! s (log (current-log)))
(log #:trace? #t s))
(define (log-value? v)
(or (eq? v #f)
(member 'cout 'cerr)
(output-port? v)
(path-string? v)))
(provide/contract
(rename *log? log? (-> any/c boolean?))
(make-log (->* (log-value?) () *log?))
(current-log (parameter/c *log?))
(log-trace! (->* (string?) (*log?) any))
)