1 ! Copyright (C) 2008 Slava Pestov.
\r
2 ! See http://factorcode.org/license.txt for BSD license.
\r
3 USING: namespaces kernel io io.files io.pathnames io.directories
\r
4 io.sockets io.encodings.utf8
\r
5 calendar calendar.format sequences continuations destructors
\r
6 prettyprint assocs math.parser words debugger math combinators
\r
7 concurrency.messaging threads arrays init math.ranges strings ;
\r
10 : log-root ( -- string )
\r
11 \ log-root get "logs" resource-path or ;
\r
13 : log-path ( service -- path )
\r
14 log-root prepend-path ;
\r
16 : log# ( path n -- path' )
\r
17 number>string ".log" append append-path ;
\r
21 : open-log-stream ( service -- stream )
\r
23 dup make-directories
\r
24 1 log# utf8 <file-appender> ;
\r
26 : log-stream ( service -- stream )
\r
27 log-files get [ open-log-stream ] cache ;
\r
29 : multiline-header ( -- string ) 20 CHAR: - <string> ; foldable
\r
31 : (write-message) ( msg word-name level multi? -- )
\r
33 "[" write multiline-header write "] " write
\r
35 "[" write now (timestamp>rfc3339) "] " write
\r
37 write bl write ": " write print ;
\r
39 : write-message ( msg word-name level -- )
\r
41 { [ pick empty? ] [ 3drop ] }
\r
42 { [ pick length 1 = ] [ [ first ] 2dip f (write-message) ] }
\r
44 [ [ first ] 2dip f (write-message) ]
\r
45 [ [ rest ] 2dip [ t (write-message) ] 2curry each ]
\r
50 : (log-message) ( msg -- )
\r
51 #! msg: { msg word-name level service }
\r
52 first4 log-stream [ write-message flush ] with-output-stream* ;
\r
54 : try-dispose ( stream -- )
\r
55 [ dispose ] curry [ error. ] recover ;
\r
57 : close-log ( service -- )
\r
58 log-files get delete-at*
\r
59 [ try-dispose ] [ drop ] if ;
\r
61 : (close-logs) ( -- )
\r
63 dup values [ try-dispose ] each
\r
68 : ?delete-file ( path -- )
\r
69 dup exists? [ delete-file ] [ drop ] if ;
\r
71 : delete-oldest ( service -- ) keep-logs log# ?delete-file ;
\r
73 : ?move-file ( old new -- )
\r
74 over exists? [ move-file ] [ 2drop ] if ;
\r
76 : advance-log ( path n -- )
\r
77 [ 1- log# ] 2keep log# ?move-file ;
\r
79 : rotate-log ( service -- )
\r
83 keep-logs 1 [a,b] [ advance-log ] with each ;
\r
85 : (rotate-logs) ( -- )
\r
87 log-root directory-files [ rotate-log ] each ;
\r
89 : log-server-loop ( -- )
\r
91 { "log-message" [ (log-message) ] }
\r
92 { "rotate-logs" [ drop (rotate-logs) ] }
\r
93 { "close-logs" [ drop (close-logs) ] }
\r
94 } case log-server-loop ;
\r
100 [ error. (close-logs) ]
\r
103 "Log server" spawn-server
\r
104 "log-server" set-global ;
\r
107 H{ } clone log-files set-global
\r
109 ] "logging" add-init-hook
\r