summaryrefslogtreecommitdiffstats
path: root/tcllib/modules/log/logger.man
diff options
context:
space:
mode:
Diffstat (limited to 'tcllib/modules/log/logger.man')
-rw-r--r--tcllib/modules/log/logger.man397
1 files changed, 397 insertions, 0 deletions
diff --git a/tcllib/modules/log/logger.man b/tcllib/modules/log/logger.man
new file mode 100644
index 0000000..53ea370
--- /dev/null
+++ b/tcllib/modules/log/logger.man
@@ -0,0 +1,397 @@
+[comment {-*- tcl -*- doctools manpage}]
+[comment {$Id: logger.man,v 1.26 2012/07/10 03:34:47 andreas_kupries Exp $}]
+[vset VERSION 0.9.4]
+[manpage_begin logger n [vset VERSION]]
+[keywords log]
+[keywords {log level}]
+[keywords logger]
+[keywords service]
+[moddesc {Object Oriented logging facility}]
+[titledesc {System to control logging of events.}]
+[category {Programming tools}]
+[require Tcl 8.2]
+[require logger [opt [vset VERSION]]]
+[description]
+
+[para]
+
+The [package logger] package provides a flexible system for logging messages
+from different services, at priority levels, with different commands.
+
+[para]
+
+To begin using the logger package, we do the following:
+
+[para]
+
+[example {
+ package require logger
+ set log [logger::init myservice]
+ ${log}::notice "Initialized myservice logging"
+
+ ... code ...
+
+ ${log}::notice "Ending myservice logging"
+ ${log}::delete
+}]
+
+[para]
+
+In the above code, after the package is loaded, the following things
+happen:
+
+[list_begin definitions]
+
+[call [cmd logger::init] [arg service]]
+
+Initializes the service [arg service] for logging. The service names
+are actually Tcl namespace names, so they are separated with '::'.
+The service name may not be the empty string or only ':'s.
+
+When a logger service is initialized, it "inherits" properties from its
+parents. For instance, if there were a service [term foo], and
+we did a [cmd logger::init] [arg foo::bar] (to create a [term bar]
+service underneath [term foo]), [term bar] would copy the current
+configuration of the [term foo] service, although it would of
+course, also be possible to then separately configure [term bar].
+
+If a logger service is initialized and the parent does not yet exist, the
+parent is also created.
+
+The new logger service is initialized with the default loglevel set
+with [cmd logger::setlevel].
+
+[call [cmd logger::import] [opt [option -all] ] [opt [option -force]] [opt "[option -prefix] [arg prefix]" ] [opt "[option -namespace] [arg namespace]" ] [arg service] ]
+
+Import the logger service commands into the current namespace. Without the [option -all] option
+only the commands corresponding to the log levels are imported. If [option -all] is given,
+all the [cmd \${log}::cmd] style commands are imported. If the import would overwrite a command
+an error is returned and no command is imported. Use the [option -force] option to force the import
+and overwrite existing commands without complaining.
+
+If the [option -prefix] option is given, the commands are imported with the given [arg prefix]
+prepended to their names.
+
+If the [option -namespace] option is given, the commands are imported into the given namespace. If the
+namespace does not exist, it is created. If a namespace without a leading :: is given, it is interpreted as
+a child namespace to the current namespace.
+
+[call [cmd logger::initNamespace] [arg ns] [opt [arg level]]]
+
+Convenience command for setting up a namespace for logging. Creates a
+logger service named after the namespace [arg ns] (a :: prefix is
+stripped), imports all the log commands into the namespace, and sets
+the default logging level, either as specified by [arg level], or
+inherited from a service in the parent namespace, or a hardwired
+default, [const warn].
+
+[call [cmd logger::services]]
+
+Returns a list of all the available services.
+
+[call [cmd logger::enable] [arg level]]
+
+Globally enables logging at and "above" the given level. Levels are
+[const debug], [const info], [const notice], [const warn], [const error],
+[const critical], [const alert], [const emergency].
+
+[call [cmd logger::disable] [arg level]]
+
+Globally disables logging at and "below" the given level. Levels are
+those listed above.
+
+[call [cmd logger::setlevel] [arg level]]
+
+Globally enable logging at and "above" the given level. Levels are those
+listed above. This command changes the default loglevel for new loggers
+created with [cmd logger::init].
+
+[call [cmd logger::levels]]
+
+Returns a list of the available log levels (also listed above under [cmd enable]).
+
+[call [cmd logger::servicecmd] [arg service]]
+
+Returns the [cmd \${log}] token created by [cmd logger::init] for this service.
+
+[call [cmd \${log}::debug] [arg message]]
+[call [cmd \${log}::info] [arg message]]
+[call [cmd \${log}::notice] [arg message]]
+[call [cmd \${log}::warn] [arg message]]
+[call [cmd \${log}::error] [arg message]]
+[call [cmd \${log}::critical] [arg message]]
+[call [cmd \${log}::alert] [arg message]]
+[call [cmd \${log}::emergency] [arg message]]
+
+These are the commands called to actually log a message about an
+event. [var \${log}] is the variable obtained from [cmd logger::init].
+
+[call [cmd \${log}::setlevel] [arg level]]
+
+Enable logging, in the service referenced by [var \${log}], and its
+children, at and above the level specified, and disable logging below
+it.
+
+[call [cmd \${log}::enable] [arg level] ]
+
+Enable logging, in the service referenced by [var \${log}], and its
+children, at and above the level specified. Note that this does [emph not] disable logging below this level, so you should probably use
+[cmd setlevel] instead.
+
+[call [cmd \${log}::disable] [arg level]]
+
+Disable logging, in the service referenced by [var \${log}], and its
+children, at and below the level specified. Note that this does [emph not] enable logging above this level,
+so you should probably use [cmd setlevel] instead.
+Disabling the loglevel [const emergency] switches logging off for the service and its children.
+
+[call [cmd \${log}::lvlchangeproc] [arg command]]
+[call [cmd \${log}::lvlchangeproc]]
+
+Set the script to call when the log instance in question changes its log level.
+If called without a command it returns the currently registered command. The command gets two arguments
+appended, the old and the new loglevel. The callback is invoked after all changes have been done.
+If child loggers are affected, their callbacks are called before their parents callback.
+
+[example {
+ proc lvlcallback {old new} {
+ puts "Loglevel changed from $old to $new"
+ }
+ ${log}::lvlchangeproc lvlcallback
+ }]
+
+[call [cmd \${log}::logproc] [arg level]]
+[call [cmd \${log}::logproc] [arg level] [arg command]]
+[call [cmd \${log}::logproc] [arg level] [arg argname] [arg body]]
+
+This command comes in three forms - the third, older one is deprecated
+and may be removed from future versions of the logger package.
+The current set version takes one argument, a command to be executed when the
+level is called. The callback command takes on argument, the text to
+be logged. If called only with a valid level [cmd logproc] returns the name of the command
+currently registered as callback command.
+
+[cmd logproc] specifies which command will perform the actual logging
+for a given level. The logger package ships with default commands for
+all log levels, but with [cmd logproc] it is possible to replace them
+with custom code. This would let you send your logs over the network,
+to a database, or anything else. For example:
+
+[example {
+ proc logtoserver {txt} {
+ variable socket
+ puts $socket "Notice: $txt"
+ }
+
+ ${log}::logproc notice logtoserver
+}]
+
+Trace logs are slightly different: instead of a plain text argument,
+the argument provided to the logproc is a dictionary consisting of the
+[const enter] or [const leave] keyword along with another dictionary of
+details about the trace. These include:
+
+[list_begin itemized]
+
+[item] [const proc] - Name of the procedure being traced.
+
+[item] [const level] - The stack level for the procedure invocation
+(from [cmd info] [cmd level]).
+
+[item] [const script] - The name of the file in which the procedure is
+defined, or an empty string if defined in interactive mode.
+
+[item] [const caller] - The name of the procedure calling the procedure
+being traced, or an empty string if the procedure was called from the
+global scope (stack level 0).
+
+[item] [const procargs] - A dictionary consisting of the names of arguments
+to the procedure paired with values given for those arguments ([const enter]
+traces only).
+
+[item] [const status] - The Tcl return code (e.g. [const ok],
+[const continue], etc.) ([const leave] traces only).
+
+[item] [const result] - The value returned by the procedure ([const leave]
+traces only).
+
+[list_end]
+
+[call [cmd \${log}::services]]
+
+Returns a list of the registered logging services which are children of this service.
+
+[call [cmd \${log}::servicename]]
+
+Returns the name of this service.
+
+[call [cmd \${log}::currentloglevel]]
+
+Returns the currently enabled log level for this service. If no logging is enabled returns [const none].
+
+[call [cmd \${log}::delproc] [arg command]]
+[call [cmd \${log}::delproc]]
+
+Set the script to call when the log instance in question is deleted.
+If called without a command it returns the currently registered command.
+For example:
+
+[example {
+ ${log}::delproc [list closesock $logsock]
+}]
+
+[call [cmd \${log}::delete]]
+
+This command deletes a particular logging service, and its children.
+You must call this to clean up the resources used by a service.
+
+[call [cmd \${log}::trace] [arg command]]
+
+This command controls logging of enter/leave traces for specified procedures.
+It is used to enable and disable tracing, query tracing status, and
+specify procedures are to be traced. Trace handlers are unregistered when
+tracing is disabled. As a result, there is not performance impact to a
+library when tracing is disabled, just as with other log level commands.
+
+[example {
+ proc tracecmd { dict } {
+ puts $dict
+ }
+
+ set log [::logger::init example]
+ ${log}::logproc trace tracecmd
+
+ proc foo { args } {
+ puts "In foo"
+ bar 1
+ return "foo_result"
+ }
+
+ proc bar { x } {
+ puts "In bar"
+ return "bar_result"
+ }
+
+ ${log}::trace add foo bar
+ ${log}::trace on
+
+ foo
+
+# Output:
+enter {proc ::foo level 1 script {} caller {} procargs {args {}}}
+In foo
+enter {proc ::bar level 2 script {} caller ::foo procargs {x 1}}
+In bar
+leave {proc ::bar level 2 script {} caller ::foo status ok result bar_result}
+leave {proc ::foo level 1 script {} caller {} status ok result foo_result}
+}]
+
+[call [cmd \${log}::trace] [cmd on]]
+
+Turns on trace logging for procedures registered through the [cmd trace]
+[cmd add] command. This is similar to the [cmd enable] command for other
+logging levels, but allows trace logging to take place at any level.
+
+The trace logging mechanism takes advantage of the execution trace feature
+of Tcl 8.4 and later. The [cmd trace] [cmd on] command will return an
+error if called from earlier versions of Tcl.
+
+[call [cmd \${log}::trace] [cmd off]]
+
+Turns off trace logging for procedures registered for trace logging
+through the [cmd trace] [cmd add] command. This is similar to the
+[cmd disable] command for other logging levels, but allows trace logging
+to take place at any level.
+
+Procedures are not unregistered, so logging for them can be turned back
+on with the [cmd trace] [cmd on] command. There is no overhead imposed
+by trace registration when trace logging is disabled.
+
+[call [cmd \${log}::trace] [cmd status] [opt procName] [opt ...]]
+
+This command returns a list of the procedures currently registered for
+trace logging, or a flag indicating whether or not a trace is registered
+for one or more specified procedures.
+
+[call [cmd \${log}::trace] [cmd add] [arg procName] [opt ...]]
+[call [cmd \${log}::trace] [cmd add] [opt -ns] [arg nsName] [opt ...]]
+
+This command registers one or more procedures for logging of entry/exit
+traces. Procedures can be specified via a list of procedure names or
+namespace names (in which case all procedure within the namespace
+are targeted by the operation). By default, each name is first
+interpreted as a procedure name or glob-style search pattern, and if
+not found its interpreted as a namespace name. The [arg -ns] option can
+be used to force interpretation of all provided arguments as namespace names.
+
+Procedures must be defined prior to registering them for tracing
+through the [cmd trace] [cmd add] command. Any procedure or namespace
+names/patterns that don't match any existing procedures will be
+silently ignored.
+
+[call [cmd \${log}::trace] [cmd remove] [arg procName] [opt ...]]
+[call [cmd \${log}::trace] [cmd remove] [opt -ns] [arg nsName] [opt ...]]
+
+This command unregisters one or more procedures so that they will no
+longer have trace logging performed, with the same matching rules as
+that of the [cmd trace] [cmd add] command.
+
+[list_end]
+
+[section IMPLEMENTATION]
+
+The logger package is implemented in such a way as to optimize (for
+Tcl 8.4 and newer) log procedures which are disabled. They are
+aliased to a proc which has no body, which is compiled to a no op in
+bytecode. This should make the peformance hit minimal. If you really
+want to pull out all the stops, you can replace the ${log} token in
+your code with the actual namespace and command (${log}::warn becomes
+::logger::tree::myservice::warn), so that no variable lookup is done.
+This puts the performance of disabled logger commands very close to no
+logging at all.
+
+[para]
+
+The "object orientation" is done through a hierarchy of namespaces.
+Using an actual object oriented system would probably be a better way
+of doing things, or at least provide for a cleaner implementation.
+
+[para]
+
+The service "object orientation" is done with namespaces.
+
+[section {Logprocs and Callstack}]
+
+The logger package takes extra care to keep the logproc out of the call stack.
+This enables logprocs to execute code in the callers scope by using uplevel or
+linking to local variables by using upvar. This may fire traces with all usual
+side effects.
+
+[example {
+ # Print caller and current vars in the calling proc
+ proc log_local_var {txt} {
+ set caller [info level -1]
+ set vars [uplevel 1 info vars]
+ foreach var [lsort $vars] {
+ if {[uplevel 1 [list array exists $var]] == 1} {
+ lappend val $var <Array>
+ } else {
+ lappend val $var [uplevel 1 [list set $var]]
+ }
+ }
+ puts "$txt"
+ puts "Caller: $caller"
+ puts "Variables in callers scope:"
+ foreach {var value} $val {
+ puts "$var = $value"
+ }
+ }
+
+ # install as logproc
+ ${log}::logproc debug log_local_var
+ }
+]
+
+[vset CATEGORY logger]
+[include ../doctools2base/include/feedback.inc]
+[manpage_end]