How is logging used in Nengo?

I’m trying to switch from using print() to the logging module for debugging based on the assumption that:

  • Using logging will allow me to quickly enable and disable what’s being logged
  • logging has built-in file and formatting utilities
  • The built-in levels of logging are helpful

To understand how to use logging better, I thought I would look at how it’s used in Nengo. However, I’m a bit confused. Nengo has it’s own logging utilities and I see a lot of:

  • logger = logging.getLogger(__name__) which I know sets the name of the logger to the current module
  • logger.debug('some message') which sends a message to the DEBUG level of the log

But where does the log file and the log level get chosen? How is logging intended to be used in Nengo? Are my assumptions about the utility of logging correct?

I think the Logging HOWTO might answer some of your questions.

I believe Nengo is not choosing a log file or a log level by itself. Thus, the defaults get used: Printing to the command line and a log level of 'warning'. We provide the convenience function nengo.utils.logging.log(...) to quickly set up logging to a file and a different log level. If I need logging output, I usually put a nengo.log('debug') or nengo.log('info') at the beginning of my script.

I mainly use it in Nengo to get information about what Nengo is doing that I could not get easily otherwise. For example, it is used in the cache to log hits and misses. That allows me to determine whether the cache is correctly working. From the outside the same decoders are returned for a hit and a miss, so I could not tell otherwise. Another example is the optimizer where I log information on the number of passes and reduction in the number of operators whereas the final model should exactly do the same.

I don’t use logging for ad-hoc debugging output that I intend to remove after diagnosing the problem. Though for complex problems the ability to have some control over the messages produced could be helpful.

1 Like

To add to what @jgosmann answered, the reason why we don’t set a log level and log file is because Nengo is intended to be used as a library. What happens in logging is, for the most part, global, so libraries should not modify it without the user’s permission. It’s super frustrating when your own logging handlers etc aren’t working properly and it turns out it’s because you imported some library that messed with the logging handlers without you realizing it. We provide nengo.log as a way for users to opt-in to printing out log messages to the console (or to a file is a path is passed).

By contrast, Nengo GUI is an application (as opposed to a library). We expect most people to be running the GUI from the command line, and not really importing it and using it in their own applications. Because of that, it wouldn’t be unusual for Nengo GUI to actually modify the global state in logging. It could even read the log messages from libraries it imports to get a complete picture of some bug that a user experiences.

1 Like

Thanks! That answered all the questions I had. I’ll close the topic now.

1 Like