1 # HOWTO: Using MashLog to log messages.
2 # MashLog provides a general logging facility in Mash. Programmers can
3 # define multiple logging channel, identified by a "type". Three types
4 # of logging channels are predefined, "info", "warn", and "error".
5 # Additional logging channels, (such as "debug") can be defined using
6 # the "file" method. Each type is associated with exactly one file
7 # channel, but a channel can be shared by different types. Messages
8 # will be sent to the channel associated with its type. For example,
9 # by default "info" is associated with "stdout" and "warn"/"error" are
10 # associated with "stderr". To send a message use "log" command.
11 #
12 # Example:
13 # MashLog file "info" stdout
14 # # Print "Hello World" to stdout.
15 # MashLog log "info" "Hello World!"
16 # MashLog file "info" info.log
17 # MashLog log "info" "Hello World!"
18 #
19 # Programmers can change the channel by reissuing the "file" method.
20 # For simplicity, everytime a "file" method is called, a new method
21 # named "type" is created.
22 #
23 # MashLog file "debug" stdout
24 # MashLog debug "foobar"
25 #
26 # You can turn timestamping and pid printing on and off.
27 # MashLog timestamp on
28 # MashLog debug "foobar"
29 # MashLog pid on
30 # MashLog debug "foobar"
31 #
32 # The following keyword are reserved and cannot be used to name
33 # message types -- "log", "show", "pid", "timestamp", "file", "all".
34 # The first five are methods already exist in MashLog and the last
35 # are used to refered to all defined types. So for example,
36 # MashLog file "all" stdout
37 # redirects all messages to stdout.
38 #
39 # The following command can help with debugging MashLog.
40 # MashLog show
41 #
42 # Logging can be turned on and off. If it is turned off, all logging
43 # methods are ignored.
44 #
45
46
47 #---------------------------------------------------------------------
48 # Class:
49 # MashLog
50 # Description:
51 # Implementation of general logging facility in Mash.
52 #---------------------------------------------------------------------
53 Class MashLog
54
55 # Turn logging on by default.
56 MashLog set on_ 1
57
58 #---------------------------------------------------------------------
59 # Method:
60 # MashLog file
61 # Description:
62 # Create a new channel, and a new procedure for logging
63 # messages.
64 # Arguments:
65 # type --
66 # channel_name --
67 #---------------------------------------------------------------------
68 MashLog proc file { type channel_name } {
69 $self instvar chan_by_type_ chan_by_name_ ref_count_ name_by_type_
70
71 # typs is "all" means do this for all existing type.
72 if {$type == "all"} {
73 foreach type [array names chan_by_type_] {
74 MashLog file $type $channel_name
75 }
76 return
77 }
78
79 if {[lsearch {file log pid timestamp} $type] != -1} {
80 error "$type is a reserved word and cannot be used as log type."
81 }
82
83 # Clean up existing channel
84 if {[info exists chan_by_type_($type)]} {
85 if {$chan_by_type_($type) != "stdout" &&
86 $chan_by_type_($type) != "stderr"} {
87 incr ref_count_($chan_by_type_($type)) -1
88 if {$ref_count_($chan_by_type_($type)) == 0} {
89 # noone is using this channel, close it.
90 close $chan_by_type_($type)
91 set oldname $name_by_type_($type)
92 unset chan_by_name_($oldname)
93 }
94 }
95 }
96
97 set name_by_type_($type) $channel_name
98
99 # A file with that name is already open, share it with this
100 # channel.
101 if [info exists chan_by_name_($channel_name)] {
102 set chan_by_type_($type) $chan_by_name_($channel_name)
103 incr ref_count_($chan_by_type_($type))
104 } else {
105 if {$channel_name != "stdout" && $channel_name != "stderr"} {
106 if {[catch {open $channel_name "w"} f]} {
107 puts stderr "Unable to open log channel $channel_name"
108 }
109 } else {
110 set f $channel_name
111 }
112 set chan_by_type_($type) $f
113 set chan_by_name_($channel_name) $f
114 set ref_count_($chan_by_type_($type)) 1
115 }
116 MashLog proc $type { msg } "
117 MashLog log $type \$msg
118 "
119 }
120
121
122 #---------------------------------------------------------------------
123 # Method:
124 # MashLog log
125 # Description:
126 # Print a message to channel with id "type". If no such type is
127 # defined, do nothing.
128 #---------------------------------------------------------------------
129 MashLog proc log { type msg } {
130 $self instvar chan_by_type_ timestamp_ pid_ on_
131 if {!$on_} {
132 return
133 }
134 if {[info exists timestamp_($type)]} {
135 set msg "[lrange [gettimeofday ascii] 1 3] $msg"
136 #set msg "\[[clock clicks -milliseconds]\] $msg"
137 }
138 if {[info exists pid_($type)]} {
139 set msg "\[$pid_($type)\] $msg"
140 }
141 if {[info exists chan_by_type_($type)]} {
142 puts $chan_by_type_($type) $msg
143 flush $chan_by_type_($type)
144 }
145 }
146
147
148 #---------------------------------------------------------------------
149 # Method:
150 # MashLog timestamp
151 # Description:
152 # Print a message to channel with id "type"
153 #---------------------------------------------------------------------
154 MashLog proc timestamp { type {onoff ""} } {
155 $self instvar timestamp_ chan_by_type_
156
157 if {$type == "all"} {
158 foreach t [array names chan_by_type_] {
159 MashLog timestamp $t $onoff
160 }
161 return
162 }
163 if ![info exists chan_by_type_($type)] {
164 error "no such channel $type"
165 }
166 if {$onoff == ""} {
167 if [info exists timestamp_($type)] {
168 return on
169 } else {
170 return off
171 }
172 } else {
173 if {$onoff == "on"} {
174 set timestamp_($type) on
175 } else {
176 unset timestamp_($type)
177 }
178 }
179 }
180
181
182 #---------------------------------------------------------------------
183 # Method:
184 # MashLog pid
185 # Description:
186 # Print a message to channel with id "type"
187 #---------------------------------------------------------------------
188 MashLog proc pid { type {onoff ""} } {
189 $self instvar pid_ chan_by_type_
190 if {$type == "all"} {
191 foreach t [array names chan_by_type_] {
192 MashLog pid $t $onoff
193 }
194 return
195 }
196 if ![info exists chan_by_type_($type)] {
197 error "no such channel $type"
198 }
199 if {$onoff == ""} {
200 if [info exists pid_($type)] {
201 return on
202 } else {
203 return off
204 }
205 } else {
206 if {$onoff == "on"} {
207 set pid_($type) [pid]
208 } else {
209 unset pid_($type)
210 }
211 }
212 }
213
214
215 #---------------------------------------------------------------------
216 # Method:
217 # MashLog off
218 # Description:
219 # Turned off all logging.
220 #---------------------------------------------------------------------
221 MashLog proc off { } {
222 $self instvar on_
223 set on_ 0
224 }
225
226
227 #---------------------------------------------------------------------
228 # Method:
229 # MashLog on
230 # Description:
231 # Turned on all logging.
232 #---------------------------------------------------------------------
233 MashLog proc on { } {
234 $self instvar on_
235 set on_ 1
236 }
237
238
239 #---------------------------------------------------------------------
240 # Method:
241 # MashLog show
242 # Description:
243 # Return all existing types and their filename.
244 #---------------------------------------------------------------------
245 MashLog proc show { } {
246 $self instvar chan_by_type_
247 return [array get chan_by_type_]
248 }
249
250 MashLog file info stdout
251 MashLog file warn stderr
252 MashLog file error stderr
253 # 7319752
254 # vim:ts=8:sw=4:expandtab
255
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.