My Perspective Logger Component

So, I’m relatively new to ignition, but have enough experience to know that logging can be difficult at times, at least in perspective apps. So, I made a logger component that I thought I’d share in case it helps someone else (or in case people can tell me how I’ve over engineered another problem :sweat_smile:):

The startup script for the component instantiates a singleton object which stores a reference to the component (sort of a singleton. I used a borg pattern I found mentioned around the web in a few places. I’m new to Python cough I mean Jython too). Here’s my script file, simply named logger:

import datetime

debugTagPath = "[default]Debug_" + system.util.getProjectName()
loggerDockName = "Logger"

class Borg:
	_shared_state = {}
	def __init__(self):
		self.__dict__ = self._shared_state

class Logger(Borg):
	def __init__(self, componentInstance = None):
		Borg.__init__(self)
		if componentInstance:
			self.componentInstance = componentInstance
	def log(self, msg):
		if hasattr(self, 'componentInstance') and system.tag.exists(debugTagPath) and system.tag.readBlocking([debugTagPath])[0].value == True:
			self.componentInstance.params.text = logTimestamp() + str(msg) + "\n" + self.componentInstance.params.text
	 		system.perspective.openDock(loggerDockName)

def log(msg):
  Logger().log(msg)
  
def logTimestamp():
	return '[' + datetime.datetime.now().strftime("%m/%d/%Y %X.%f")[:-3] + ']: '

And here’s the startup script for the logger component:

def runAction(self):
	"""
	Method that will run whenever the selected event fires.

	Arguments:
		self: A reference to the component that is invoking this function.
	"""
	logger.Logger(self)

It also makes use of boolean memory tags to check if it’s in a debug environment or not. My project has several copies for versioning, some of which are dev or testing, and some are production. So the boolean memory tags are named Debug_<project_name>, so that a project can check if it should produce logs.

The component itself is nothing special, just a text area with text bound to view.params.text, as well as Clear and Close buttons

I mounted the component in the south dock, with display: onDemand and handle: hide. Then, I can place logger.log('Hey folks!') somewhere in a script, and Voila!:

It’s still nowhere near as lean and unobtrusive as console.log statements, but it has helped me quite a bit so far, so I thought I’d share!

Not to discount the (very cool!) engineering effort, but it’s worth pointing out that system.perspective.print will end up as a console.log if you don’t specify a different target parameter.

2 Likes

Thank you! I knew there must be something like this :smile:

On that note, I feel like this command should be a little more prominent in the documentation, as console logs are the most commonly used debugging tool in web development. I may have missed it, but I didn’t see it mentioned in the Inductive University videos I watched.

Also, this command doesn’t appear in the top results for either log, logging, or even for print in the ignition docs. This may account for the fact that neither I nor my colleagues were aware of this command. Either that or we experienced some kind of communal blindspot :joy:

I want to add that the Inductive University lessons have been a fantastic resource!

Thanks again!

1 Like

@kjordan, I know this is from a few years ago, but it’s exactly what I was looking to implement. Thanks for sharing.

Double cool because I haven’t spent much time looking through the system.perspective.* api yet.
@PGriffith, would you guys consider adding the ability to have a component be a log sink?