1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
# Copyright (C) 2017 Free Software Foundation, Inc.
#
# Permission is granted to copy, distribute and/or modify this document
# under the terms of the GNU Free Documentation License, Version 1.3
# or any later version published by the Free Software Foundation;
# with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
# A copy of the license is included in the section entitled "GNU
# Free Documentation License".
/*! \page page_logger Logging
\section logging Logging
GNU Radio has a logging interface to enable various levels of logging
information to be printed to the console or a file. The logger derives
from log4cpp (http://log4cpp.sourceforge.net/) which is readily
available in most Linux distributions. This is an optional dependency
and GNU Radio will work without it.
When configuring GNU Radio, the -DENABLE_GR_LOG=On|Off option to cmake
will allow the user to toggle use of the logger on and off. The logger
defaults to "on" and will use log4cpp if it is available. If log4cpp
is not found, the default logging will output to standard output or
standard error, depending on the level of the log message.
Logging is useful for blocks to print out certain amounts of data at
different levels. These levels are:
<pre>
DEBUG < INFO < WARN < TRACE < ERROR < ALERT < CRIT < FATAL < EMERG
</pre>
The order here determines the level of output. These levels are
hierarchical in that specifying any level also includes any level
above it. For example, when using the INFO level, all INFO and
higher messages are logged and DEBUG is ignored. A level NOTSET is provided
to disable a logger.
\subsection configfile Logging Configuration
The logging configuration can be found in the gnuradio-runtime.conf file
under the [LOG] section. This allows us fairly complete control over
the logging facilities. The main configuration functions are to set up
the level of the loggers and set the default output behavior of the
loggers.
There are two default loggers that all gr_block's have access to:
d_logger and d_debug_logger. The first is a standard logger meant to
output simple information about the block while it is running. The
debug logger is meant for debugging purposes and is added to make it
convenient to use a secondary logger that outputs to a different
stream or file.
The four main configure options are:
<pre>
log_level = debug
debug_level = debug
log_file = stdout
debug_file = stderr
</pre>
This establishes the two loggers as having access to all levels of
logging events (DEBUG through EMERG). They are also configured not to
use files but instead output to the console. The standard logger will
output to standard out while the debug logger outputs to standard
error.
Changing these last two lines to another value will create files that
are used to store the log messages. All messages are appended to the
file.
When using either standard error or standard out, the messages for the
two different loggers will look like:
<pre>
gr::log :\<level\>: \<block alias\> - \<message\>
gr::debug :\<level\>: \<block alias\> - \<message\>
</pre>
When using a file, the only difference in the format is that the
message prefix of "gr::log" or "gr::debug" is not used. Instead, the
time in milliseconds from the start of the program is inserted.
Remember that a local "~/.gnuradio/config.conf" file can be used to
override any parameter in the global file (see \ref prefs for more
details).
To use these loggers inside of a GNU Radio block, we use the protected
data members of d_logger and d_debug_logger of gr_block and pass them
to our pre-defined macros:
\code
GR_LOG_<level>(<logger>, "<Message to print>");
\endcode
Where \<level\> is one of the levels as mentioned above, \<logger\> is
either d_logger or d_debug_logger, and \<Message to print\> is the
message we want to output. If we wanted to output an INFO level
message to the standard logger and a WARN level message to the debug
logger, it would look like this:
\code
GR_LOG_INFO(d_logger, "Some info about the block");
GR_LOG_WARN(d_debug_logger, "Some warning about the block");
\endcode
When this is printed to wherever you are directing the output of the
logger, it will look like:
<pre>
gr::log :INFO: <block's alias> - Some info about the block
gr::debug :WARN: <block's alias> - Some warning about the block
</pre>
This provides us information about where the message came from, the
level of the message, and the block that generated the message. We use
the concept of the block's alias which by default (i.e., unless
otherwise set by the user) includes the name of the block and a unique
ID to distinguish it from other blocks of the same type.
The various logging macros are defined in gr_logger.h. Here are some
simple examples of using them:
\code
GR_LOG_DEBUG(LOG, "DEBUG message");
GR_LOG_INFO(LOG, "INFO message");
GR_LOG_NOTICE(LOG, "NOTICE message");
GR_LOG_WARN(LOG, "WARNING message");
GR_LOG_ERROR(LOG, "ERROR message");
GR_LOG_CRIT(LOG, "CRIT message");
GR_LOG_ALERT(LOG, "ALERT message");
GR_LOG_FATAL(LOG, "FATAL message");
GR_LOG_EMERG(LOG, "EMERG message");
\endcode
If the logger is not enabled, then these macros become nops and do
nothing (and d_logger and d_debug_logger are NULL pointers). If
logging is enabled but the log4cpp library is not found, then TRACE,
INFO, and NOTICE levels go to stdout and the rest to stderr.
\subsection adv_config Advanced Configuration Options
If not using the simplified settings discussed above, where we can
direct the logger messages to either a file or one of the standard
outputs, we must use a more complicated configuration file. We do this
by specifying the "log_config" option in the [LOG] section. The
log4cpp documentation will provide more information on how
configuration works and looks. Mostly, a default configuration script
provided with GNU Radio can be used. After installation, the default
configuration script is located at:
<pre>
$prefix/etc/gnuradio/gr_log_default.conf
</pre>
For the following examples, we will assume that our local
"~/.gnuradio/config.conf" looks like this:
\code
[LOG]
log_config = /opt/gr/etc/gnuadio/gr_log_default.conf
log_level = debug
debug_level = Off
\endcode
Inside of the default configuration file, we define the parameters
for the two logger's, the standard logger the separate debug logger.
If the levels of the two loggers are specified in our configuration
file, as in the above example, these levels override any levels
specified in the XML file. Here, we have turned on the standard logger
(d_logger) to all levels and turned off the debug logger
(d_debug_logger). So even if the debug logger is used in the code, it
will not actually output any information. Conversely, any level of
output passed to the standard logger will output because we have
turned this value to the lowest level "debug."
If both an XML configuration file is set and the "log_file" or
"debug_file" options are set at the same time, both systems are
actually used. So you can configure file access and the pattern
through the XML file while also still outputting to stdout or stderr.
\section advlog Advanced Usage
The description above for using the logging facilities is specific to
GNU Radio blocks. We have put the code necessary to access the
debugger into the gr_block parent class to simplify access and make
sure all blocks have the ability to quickly and easily use the logger.
For non gr_block-based code, we have to get some information about the
logger in order to properly access it. Each logger only exists once as
a singleton in the system, but we need to get a pointer to the right
logger and then set it up for our local use. The following code
snippet shows how to do this to get access to the standard logger,
which has a root of "gr_log." (access to the debug logger is similar
except we would use "gr_log_debug." in the GR_LOG_GETLOGGER call):
\code
prefs *p = prefs::singleton();
std::string log_file = p->get_string("LOG", "log_config", "");
std::string log_level = p->get_string("LOG", "log_level", "off");
GR_CONFIG_LOGGER(log_file);
GR_LOG_GETLOGGER(LOG, "gr_log." + "my_logger_name");
GR_LOG_SET_LEVEL(LOG, log_level);
\endcode
This creates a pointer called LOG (which is instantiated as a
log4cpp:LoggerPtr in the macro) that we can now use locally as the
input to our logging macros like 'GR_LOG_INFO(LOG, "message")'.
\section logPy Logging from Python
The logging capability has been brought out python via swig. The configuration
of the logger can be manipulated via the following calls:
\code
from gnuradio import gr
gr.logger_config(filename,watch_period) # Configures the logger with conf file filename
names = gr.logger_get_names() # Returns the names of all loggers
gr.logger_reset_config() # Resets logger config by removing all appenders
\endcode
Once the logger is configured you can manipulate a logger via a wrapper class gr.logger().
You can isntantiate this by the following. (Reference logger.h for list of methods)
\code
from gnuradio import gr
log=gr.logger("nameOfLogger")
log.debug("Log a debug message")
log.set_level("INFO");
\endcode
*/
|