A universal way to alert devleopers about errors?

I recently made a post about universal print function, and now I am realizing I kind of need a universal error handling function as well.

Vision currently works fine with this, I just
raise DeveloperError("something went wrong") and I get the stack tract

Perspective doesn’t give a popup when you raise an error, I get why, its in a web browser/js/react environment, that’s not really something that’s done out of the box. But I would like it to be for my project.

I made a custom errorPopup for perspective where I can feed the error as the param. But it only gives me the error I type, not the full stack.

Here’s my current attempt:

def universalError(error):
	"""
	We should have some way to really notify a developer if something went very wrong.
	Vision is easy, we can raise an error, but perspective is trickier and we need alternatives.
	This is all for client side stuff.  Gateway scripts should be more like try: except: log error, since raise an exception will not help us out much
	
	Convenion:
		we always raise a DevError, since it's custom, and won't be thrown by other built in scripts
	Args:
		error: str, what is the error
	Returns:
		either raise alert, or some popup window for perspective
	"""	
	from new_dev.errors import DeveloperError
	from env import isVision
	if isVision():
		raise DeveloperError(error)
	else:
		import system.perspective
		system.perspective.openPopup('errorPopupId','Errors/genericError', params = {'error':error})

Vision module is working fine, but with perspective I’m only seeing the top string being fed. I get why - that’s all I am giving as a param. But I would like the full stack trace. I don’t know how to do that without raising an error, but that too would also stop my script so I don’t know how I’d then get that and then feed it to my openPopup script.

Any ideas?

The error (whether a Py exception or Java exception) should have a getStackTrace() method that returns an array of StackTraceElements that you can then examine to get line numbers and details.

1 Like

Here’s how I call the universalError, perhaps this is where my issue is and I should change how I do this?

I made the first two conditions false just to force an error right now.

def universalError(error):
	"""
	We should have some way to really notify a developer if something went very wrong.
	Vision is easy, we can raise an error, but perspective is trickier and we need alternatives.
	This is all for client side stuff.  Gateway scripts should be more like try: except: log error, since raise an exception will not help us out much
	
	Convenion:
		we always raise a DevError, since it's custom, and won't be thrown by other built in scripts
	Args:
		error: str, what is the error
	Returns:
		either raise alert, or some popup window for perspective
	"""	
	from new_dev.errors import DeveloperError
	from env import isVision
	if isVision():
		raise DeveloperError(error)
	else:
		import system.perspective
		system.perspective.openPopup('errorPopupId','Errors/genericError', params = {'error':error})

def getData(container, prefix="_out_"):
"""
Use this to get data from the root container(vision) or view(perspective)
"""
	from test import universalPrint as uPrint, universalError
	uPrint(str(type(container)))
	if False:
		uPrint("vision")	
	elif False:
		uPrint("perspective")
	else:
		universalError("Unsupported type %s"%(str(type(container))))

Perhaps I should be trying to do this differently?

Oh, I see. Just throw an exception manually to get access to the object, maybe something like:

def universalError(error):
	"""
	We should have some way to really notify a developer if something went very wrong.
	Vision is easy, we can raise an error, but perspective is trickier and we need alternatives.
	This is all for client side stuff.  Gateway scripts should be more like try: except: log error, since raise an exception will not help us out much
	
	Convenion:
		we always raise a DevError, since it's custom, and won't be thrown by other built in scripts
	Args:
		error: str, what is the error
	Returns:
		either raise alert, or some popup window for perspective
	"""	
	from new_dev.errors import DeveloperError
	from env import isVision
	if env.isVision():
		raise DeveloperError(error)
	else:
		try:
			raise DeveloperError(error)
		except DeveloperError, ex:
			import system.perspective
			system.perspective.openPopup('errorPopupId','Errors/genericError', params = {'error':ex})
1 Like

Really? I’ve always used traceback… do you mean I don’t need to import the traceback module?

Something like below is what I use on most all of my gateway scripts so I know if something goes wrong

try:
    # Something!
except Exception, e:
		shared.util.sendEmailErrorReport('description', traceback.format_exc().replace('\n','<br>'))
		raise
	except java.lang.Exception, e:
		shared.util.sendEmailErrorReport('description', traceback.format_exc().replace('\n','<br>'))
		raise

Unless Jython is doing something funky behind the scenes, the PyException (Java) class that forms the backing for all Jython exceptions extends from java.lang.Throwable, which is where getStacktrace() comes from. That said, the Java stacktrace for failing Python code can be cryptic; there’s a lot of PyTable and PyFrame and similar ‘backend’ code for the Jython interpreter that may not be as useful as what you get out of traceback (I don’t actually know what the traceback output looks like).

It does not. That’s why you may need separate except clauses for java vs. jython. See my later.py script module for some hints on how to handle this.

Oh, right. You prompted me to dig deeper; PyException does extend RuntimeException, but it’s only generally used by Jython for syntax errors - within the Jython interpreter, everything extends PyBaseException…although there is some complicated stuff in the PyException class that makes me think there might be some way to bridge things in a generic way. Maybe not from within the Jython interpreter, though.

Uhm? My PythonAsJavaException class?

What, I’m supposed to read these links you’re posting?! :laughing:

1 Like

Tsk. (;

Anyways, my PythonAsJavaException class is handy when you want to log with the python backtrace, or inject a python exception as the cause for a java exception. I’ve been meaning to rewrite it in java and make it part of Simulation Aids… too much on my to-do list. /:

1 Like