View | Details | Raw Unified | Return to bug 91
Collapse All | Expand All

(-)a/src/core/log.cc (-173 / +105 lines)
 Lines 17-22    Link Here 
17
 *
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 */
19
 */
20
21
// What about print-list!!!!!!???????
20
22
21
#ifdef NS3_LOG_ENABLE
23
#ifdef NS3_LOG_ENABLE
22
24
 Lines 44-112   ComponentList *GetComponentList (void) Link Here 
44
  return &components;
46
  return &components;
45
}
47
}
46
48
49
LogComponent::LogComponent (char const * name)
50
  : m_levels (0), m_name (name)
51
{
52
  EnvVarCheck (name);
53
54
  ComponentList *components = GetComponentList ();
55
  for (ComponentListI i = components->begin ();
56
       i != components->end ();
57
       i++)
58
    {
59
      NS_ASSERT (i->first != name);
60
    }
61
  components->push_back (std::make_pair (name, this));
62
}
63
47
void
64
void
48
LogComponentEnableEnvVar (void)
65
LogComponent::EnvVarCheck (char const * name)
49
{
66
{
50
  static bool isFirstLog = true;
51
#if 0
52
//
53
// Interesting static constructor bug:
54
//
55
// The RandomDirection2dMobilityModel declares a RandomVariableDefaultValue
56
// g_speedVariable.  This variable is initialized in the 
57
// static_initialization_and_destruction_0 function as expected.  This causes
58
// RandomVariableDefaultValue::Parse () to be called which calls NS_LOG_X
59
// functions.  The macro calls LogComponent::IsEnabled () which calls 
60
// LogComponentEnableEnvVar ().  The following variable called isFirstLog
61
// is set after the first call to prevent the environment variable from
62
// actually being parsed on every log call.
63
//
64
// When the RandomDirection2dMobilityModel static constructor is run, other
65
// log components may not have had their static constructors run yet.  It is
66
// in those other static constructors that their log components are added to
67
// the list of log components.
68
//
69
// The end result is that if any code calls an NS_LOG_X function during its
70
// static constructor, the environment variable check is "locked out" for 
71
// any log component declarations (in different compilation units) that have
72
// not yet been executed.
73
//
74
// So, the choice seems to be to either 1) parse the environment variables
75
// at every log call; or 2) make LogComponentEnableEnvVar explicitly called
76
// after all other static constructors are called.  This means in main ().
77
// The former choice seems the only reasonable way out if we care remotely
78
// about performance in logging.
79
//
80
// I made LogComponentEnableEnvVar a public API that you need to call in 
81
// main () if you want to use environment variables to drive the log output.
82
// 
83
  if (!isFirstLog)
84
    {
85
      return;
86
    }
87
#endif // 0
88
89
#ifdef HAVE_GETENV
67
#ifdef HAVE_GETENV
90
  char *envVar = getenv("NS_LOG");
68
  char *envVar = getenv("NS_LOG");
91
  if (envVar == 0)
69
  if (envVar == 0)
92
    {
70
    {
93
      isFirstLog = false;
94
      return;
71
      return;
95
    }
72
    }
96
  std::string env = envVar;
73
  std::string env = envVar;
97
  if (env == "print-list")
74
  std::string myName = name;
98
    {
75
99
      LogComponentPrintList ();
100
      isFirstLog = false;
101
      return;
102
    }
103
  if (env == "*")
104
    {
105
      LogComponentEnableAll (LOG_DEBUG);
106
      isFirstLog = false;
107
      return;
108
    }
109
  bool allFound = true;
110
  std::string::size_type cur = 0;
76
  std::string::size_type cur = 0;
111
  std::string::size_type next = 0;
77
  std::string::size_type next = 0;
112
  while (true)
78
  while (true)
 Lines 128-244   LogComponentEnableEnvVar (void) Link Here 
128
        }
94
        }
129
      std::string::size_type equal = tmp.find ("=");
95
      std::string::size_type equal = tmp.find ("=");
130
      std::string component;
96
      std::string component;
131
      int level = 0;
132
      if (equal == std::string::npos)
97
      if (equal == std::string::npos)
133
        {
98
        {
134
          component = tmp;
99
          component = tmp;
135
          level = LOG_DEBUG;
100
          if (component == myName || component == "*")
101
            {
102
              Enable (LOG_DEBUG);
103
              return;
104
            }
136
        }
105
        }
137
      else
106
      else
138
        {
107
        {
139
          component = tmp.substr (0, equal);
108
          component = tmp.substr (0, equal);
140
          std::string::size_type cur_lev;
109
          if (component == myName || component == "*")
141
          std::string::size_type next_lev = equal;
142
          do
143
            {
110
            {
144
              cur_lev = next_lev + 1;
111
              int level = 0;
145
              next_lev = tmp.find ("|", cur_lev);
112
              std::string::size_type cur_lev;
146
              std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
113
              std::string::size_type next_lev = equal;
147
              if (lev == "error")
114
              do
148
                {
115
                {
149
                  level |= LOG_ERROR;
116
                  cur_lev = next_lev + 1;
150
                }
117
                  next_lev = tmp.find ("|", cur_lev);
151
              else if (lev == "warn")
118
                  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
152
                {
119
                  if (lev == "error")
153
                  level |= LOG_WARN;
120
                    {
154
                }
121
                      level |= LOG_ERROR;
155
              else if (lev == "debug")
122
                    }
156
                {
123
                  else if (lev == "warn")
157
                  level |= LOG_DEBUG;
124
                    {
158
                }
125
                      level |= LOG_WARN;
159
              else if (lev == "info")
126
                    }
160
                {
127
                  else if (lev == "debug")
161
                  level |= LOG_INFO;
128
                    {
162
                }
129
                      level |= LOG_DEBUG;
163
              else if (lev == "function")
130
                    }
164
                {
131
                  else if (lev == "info")
165
                  level |= LOG_FUNCTION;
132
                    {
166
                }
133
                      level |= LOG_INFO;
167
              else if (lev == "param")
134
                    }
168
                {
135
                  else if (lev == "function")
169
                  level |= LOG_PARAM;
136
                    {
170
                }
137
                      level |= LOG_FUNCTION;
171
              else if (lev == "logic")
138
                    }
172
                {
139
                  else if (lev == "param")
173
                  level |= LOG_LOGIC;
140
                    {
174
                }
141
                      level |= LOG_PARAM;
175
              else if (lev == "all")
142
                    }
176
                {
143
                  else if (lev == "logic")
177
                  level |= LOG_ALL;
144
                    {
178
                }
145
                      level |= LOG_LOGIC;
179
              else if (lev == "prefix")
146
                    }
180
                {
147
                  else if (lev == "all")
181
                  level |= LOG_PREFIX_ALL;
148
                    {
182
                }
149
                      level |= LOG_ALL;
183
              else if (lev == "level_error")
150
                    }
184
                {
151
                  else if (lev == "prefix")
185
                  level |= LOG_LEVEL_ERROR;
152
                    {
186
                }
153
                      level |= LOG_PREFIX_ALL;
187
              else if (lev == "level_warn")
154
                    }
188
                {
155
                  else if (lev == "level_error")
189
                  level |= LOG_LEVEL_WARN;
156
                    {
190
                }
157
                      level |= LOG_LEVEL_ERROR;
191
              else if (lev == "level_debug")
158
                    }
192
                {
159
                  else if (lev == "level_warn")
193
                  level |= LOG_LEVEL_DEBUG;
160
                    {
194
                }
161
                      level |= LOG_LEVEL_WARN;
195
              else if (lev == "level_info")
162
                    }
196
                {
163
                  else if (lev == "level_debug")
197
                  level |= LOG_LEVEL_INFO;
164
                    {
198
                }
165
                      level |= LOG_LEVEL_DEBUG;
199
              else if (lev == "level_function")
166
                    }
200
                {
167
                  else if (lev == "level_info")
201
                  level |= LOG_LEVEL_FUNCTION;
168
                    {
202
                }
169
                      level |= LOG_LEVEL_INFO;
203
              else if (lev == "level_param")
170
                    }
204
                {
171
                  else if (lev == "level_function")
205
                  level |= LOG_LEVEL_PARAM;
172
                    {
206
                }
173
                      level |= LOG_LEVEL_FUNCTION;
207
              else if (lev == "level_logic")
174
                    }
208
                {
175
                  else if (lev == "level_param")
209
                  level |= LOG_LEVEL_LOGIC;
176
                    {
210
                }
177
                      level |= LOG_LEVEL_PARAM;
211
              else if (lev == "level_all")
178
                    }
212
                {
179
                  else if (lev == "level_logic")
213
                  level |= LOG_LEVEL_ALL;
180
                    {
214
                }
181
                      level |= LOG_LEVEL_LOGIC;
215
            } while (next_lev != std::string::npos);
182
                    }
216
        }
183
                  else if (lev == "level_all")
217
      bool found = false;
184
                    {
218
      if (component == "*")
185
                      level |= LOG_LEVEL_ALL;
219
        {
186
                    }
220
          found = true;
187
                } while (next_lev != std::string::npos);
221
          LogComponentEnableAll ((enum LogLevel)level);
188
222
        }
189
              Enable ((enum LogLevel)level);
223
      else
224
        {
225
          ComponentList *components = GetComponentList ();
226
          for (ComponentListI i = components->begin ();
227
               i != components->end ();
228
               i++)
229
            {
230
              if (i->first.compare (component) == 0)
231
                {
232
                  found = true;
233
                  
234
                  i->second->Enable ((enum LogLevel)level);
235
                  break;
236
                }
237
            }
190
            }
238
        }
239
      if (!found)
240
        {
241
          allFound = false;
242
        }
191
        }
243
      if (next == std::string::npos)
192
      if (next == std::string::npos)
244
        {
193
        {
 Lines 250-275   LogComponentEnableEnvVar (void) Link Here 
250
          break;
199
          break;
251
        }
200
        }
252
    }
201
    }
253
  if (allFound)
254
    {
255
      isFirstLog = false;
256
    }
257
  
258
#endif
202
#endif
259
}
203
}
260
204
261
LogComponent::LogComponent (char const * name)
262
  : m_levels (0), m_name (name)
263
{
264
  ComponentList *components = GetComponentList ();
265
  for (ComponentListI i = components->begin ();
266
       i != components->end ();
267
       i++)
268
    {
269
      NS_ASSERT (i->first != name);
270
    }
271
  components->push_back (std::make_pair (name, this));
272
}
273
205
274
bool 
206
bool 
275
LogComponent::IsEnabled (enum LogLevel level) const
207
LogComponent::IsEnabled (enum LogLevel level) const
(-)a/src/core/log.h (-28 / +16 lines)
 Lines 34-39    Link Here 
34
 *     messages, use the ns3::LogComponentEnable
34
 *     messages, use the ns3::LogComponentEnable
35
 *     function or use the NS_LOG environment variable and 
35
 *     function or use the NS_LOG environment variable and 
36
 *     ns3::LogComponentEnableEnvVar
36
 *     ns3::LogComponentEnableEnvVar
37
 *
38
 * Use the environment variable NS_LOG to define a ';'-separated list of
39
 * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
40
 * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
41
 * NS_LOG=* will enable all available log components.
42
 *
43
 * For each component, the "debug" log level is enabled by default
44
 * but more components can be enabled selectively with the following
45
 * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
46
 * This example would enable the 'func', 'param', and 'warn' log
47
 * levels for 'Component1' and the 'error' and 'debug' log levels
48
 * for 'Component2'.  The wildcard can be used here as well.  For example
49
 * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
50
 * prints with the component and function names.
51
 *
37
 */
52
 */
38
53
39
/**
54
/**
 Lines 180-207   enum LogLevel { Link Here 
180
195
181
#ifdef NS3_LOG_ENABLE
196
#ifdef NS3_LOG_ENABLE
182
/**
197
/**
183
 * \brief Enable the logging output based on an environment variable.
184
 *
185
 * Use the environment variable NS_LOG to define a ';'-separated list of
186
 * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
187
 * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
188
 * NS_LOG=* will enable all available log components.
189
 *
190
 * For each component, the "debug" log level is enabled by default
191
 * but more components can be enabled selectively with the following
192
 * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
193
 * This example would enable the 'func', 'param', and 'warn' log
194
 * levels for 'Component1' and the 'error' and 'debug' log levels
195
 * for 'Component2'.  The wildcard can be used here as well.  For example
196
 * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
197
 * prints with the component and function names.
198
 *
199
 * The list of available log components can be printed on stdout
200
 * with the NS_LOG=print-list syntax.
201
 */
202
  void LogComponentEnableEnvVar (void);
203
204
/**
205
 * \param name a log component name
198
 * \param name a log component name
206
 * \param level a logging level
199
 * \param level a logging level
207
 * \param decorate whether or not to add function names to all logs
200
 * \param decorate whether or not to add function names to all logs
 Lines 222-228   enum LogLevel { Link Here 
222
 */
215
 */
223
  void LogComponentEnableAll (enum LogLevel level);
216
  void LogComponentEnableAll (enum LogLevel level);
224
#else
217
#else
225
#define LogComponentEnableEnvVar()
226
#define LogComponentEnable(a,b)
218
#define LogComponentEnable(a,b)
227
#define LogComponentEnableAll(a)
219
#define LogComponentEnableAll(a)
228
#endif
220
#endif
 Lines 259-269   void LogComponentDisableAll (enum LogLev Link Here 
259
 * \ingroup logging
251
 * \ingroup logging
260
 *
252
 *
261
 * Print the list of logging messages available.
253
 * Print the list of logging messages available.
262
 * The output of this function can be obtained by setting
263
 * the NS_LOG environment variable to the special value 
264
 * 'print-list'.
265
 * 
266
 * For example: NS_LOG=print-list
267
 */
254
 */
268
#ifdef NS3_LOG_ENABLE
255
#ifdef NS3_LOG_ENABLE
269
void LogComponentPrintList (void);
256
void LogComponentPrintList (void);
 Lines 276-281   class LogComponent { Link Here 
276
class LogComponent {
263
class LogComponent {
277
public:
264
public:
278
  LogComponent (char const *name);
265
  LogComponent (char const *name);
266
  void EnvVarCheck (char const *name);
279
  bool IsEnabled (enum LogLevel level) const;
267
  bool IsEnabled (enum LogLevel level) const;
280
  bool IsNoneEnabled (void) const;
268
  bool IsNoneEnabled (void) const;
281
  void Enable (enum LogLevel level);
269
  void Enable (enum LogLevel level);
(-)a/tutorial/hello-simulator.cc (-5 lines)
 Lines 24-33   int Link Here 
24
int 
24
int 
25
main (int argc, char *argv[])
25
main (int argc, char *argv[])
26
{
26
{
27
  DebugComponentEnable ("Log");
28
29
  //  LogComponentEnable ("HelloSimulator", 
30
  //    LogLevel (LOG_LEVEL_INFO | LOG_PREFIX_ALL));
31
32
  NS_LOG_INFO ("Hello Simulator");
27
  NS_LOG_INFO ("Hello Simulator");
33
}
28
}

Return to bug 91