Clarification:
The purpose of logging is, I want to log message every time, such that, when glitch happened in the past, I can go thru the log message to see what was going on that time.
But this is not the case, for example, If on the script, i purposely log as "Debug", but for some reason a colleague, changed the log level to "Info". My debug message will not be log.
This beats the purpose of logging the message.
What is the reason behind this feature; a way to filter which message being logged?
Is there another strategy I can use to make sure, my log message is being log?
Logging is designed to quickly discard messages at too low a level, without even evaluating their formatting arguments, to minimize the performance penalty of logging. (Severe performance hit.)
This has the side-benefit of requiring no disk space, and therefore extending the log rotation time period of whatever logs are actually enabled.
All of Ignition's log levels are INFO at gateway startup. If you absolutely have to log something reliably, use INFO level. But think really hard about whether you really need that. Consider logging at INFO level the first time something happens (in some time period), and logging at DEBUG level after that. So users can see that something is happening, but don't get bombarded with it without need.
{ When including dynamic content in your logs, you should always use the .infof() or .debugf() logger methods. Avoid doing any complex calculations to hand to format arguments. Instead, arrange for your objects to intelligently stringify on demand from a %s placeholder. Those won't execute when the log level is disabled. }
Thanks.
I understood.
One note for each developer, Level setting in Status-Diagnostic->Log is universal and fixed.
And I recall that,
it is on developer discretion, to decide, which debug level to use for each debug message.
Thus its a normal scenario where, a developer expect something will go wrong, then only go to gateway log and set logging level to debug, and reset to info when developer is confident that everything looks good. -- i wish there was a timer.
But in a scenario where multiple developers are debugging, we don't want them to set level=Info, when you want it to be level=debug. hmm
p.s.
what is wrong with logger.info("my name is: %s" % myName")
Edit:
Another place when I want debug message to always show:
I use system.perspective.print() this will show on browser console and can display object (as oppose to only string).
For the query, well... it depends on the query. It's up to you to check the returned value and see if it corresponds to what you expects.
Don't forget that most functions can raise errors, so wrap your calls in try/except if you want to personally handle errors. And keep in mind that database related functions will raise a java error, not a python one. sendEmail might raise a java error too.
Nothing should be left going to system.perspective.print() when you are done. That is a burden on the browser connection, not just burning a bit of gateway CPU.
Do something like this (with some help from my Integration Toolkit):
# In some library
from java.lang import Throwable
logger = system.util.getLogger(system.util.getProjectName() + "." + system.reflect.getModulePath())
def someOperation(params):
try:
return system.db.runNamedQuery("path/to/query", params)
except Throwable, t:
logger.warnf("Java error in path/to/query: %s", [params], t)
except Exception, e:
logger.warnf("Jython error in path/to/query: %s", [params], system.reflect.asThrowable(e, None))
That will log errors in JDBC. You would then check the return value for expected results.
I use WARN level where the code should never fail that way without big problems. I use lesser log levels for unexpected/invalid result data.
Reading this quote raised some questions for me regarding best logging practices in our systems. I'd love to get some clarity on how Ignition handles logging under the hood:
Log Level Execution: If I log something at the debug level (logger.debug(...)) but the logger's level is set to INFO, does this "log action" still execute, or is it bypassed entirely?
Performance Impact: What is the real danger here — the log method call itself, or the logger instantiation?
Project Best Practices: Is the best approach to instantiate a single logger for an entire project so all functions use the same object, or is it better to separate the loggers with better context names?
Module Development: This question extends to module development. I am creating loggers for specific classes within my devices (it's a driver module), using a hierarchical structure like "ExampleDevice", "ExampleDevice.MessageHandler", and "ExampleDevice.MessageHandler.AlarmMessage". How many instances of loggers are "acceptable" for a module to create without hurting performance?
Logger Lifecycle: What is the lifecycle of a Logger object? When is an instance actually terminated/garbage collected?
Note: The link to the LoggerEx documentation in the Ignition User Manual is currently not working (see the attached screenshot). Maybe it would have answered some of my questions!
The .debug() method is called, but then does nothing more. It does mean the arguments to .debug() will be computed and passed, then discarded. That is why you should use .debugf(), which skips the message formatting when it can.
The hazard is constructing complex log messages just to throw them away.
Instantiate loggers as long-lived variables in the top level of project library scripts. (Outside any function definitions.) I typically use one per library script, named for the project and script path.
You should use canonical class names for your module logger names. Use a static final fields for per-class loggers. For long-lived class instances, a final field is also reasonable if you want to embed an instance name in the logger name.
Logger objects persist in the logging system for the life of the JVM, once created, IIUC.