# A universal way to alert devleopers about errors?

**URL:** <https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914>\
**Category:** Ignition\
**Tags:** ignition80\
**Created:** [May 20, 2020, 4:50pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914 "2020-05-20T16:50:30Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [May 20, 2020, 4:50pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/1 "2020-05-20T16:50:30Z")

</div>

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

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/2X/3/3b513a121bf55e278e18373ec693dfa8db026570.png)

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:

```auto
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?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 20, 2020, 5:15pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/2 "2020-05-20T17:15:17Z")

</div>

The `error` (whether a Py exception or Java exception) should have a `getStackTrace()` method that returns an array of [`StackTraceElement`s](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/StackTraceElement.html) that you can then examine to get line numbers and details.

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [May 20, 2020, 5:19pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/3 "2020-05-20T17:19:08Z")

</div>

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.

```auto
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?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 20, 2020, 6:30pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/4 "2020-05-20T18:30:31Z")

</div>

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

```auto
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})

```

---

<div class="post-metadata">

**Author:** ![ryanjmclaughlin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/ryanjmclaughlin/32/4318_2.png) [@ryanjmclaughlin](https://forum.inductiveautomation.com/u/ryanjmclaughlin)\
**Post date:** [May 21, 2020, 12:34pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/5 "2020-05-21T12:34:56Z")

</div>

> [@paul-griffith](#):
>
> The `error` (whether a Py exception or Java exception) should have a `getStackTrace()` method

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

```auto
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

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 21, 2020, 3:40pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/6 "2020-05-21T15:40:31Z")

</div>

> [@ryanjmclaughlin](#):
>
> Really? I’ve always used traceback… do you mean I don’t need to import the traceback module?

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).

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 21, 2020, 8:29pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/7 "2020-05-21T20:29:45Z")

</div>

> [@paul-griffith](#):
>
> the PyException (Java) class that forms the backing for all Jython exceptions extends from `java.lang.Throwable`

It does not. That's why you may need separate `except` clauses for java vs. jython. See my [later.py](https://www.automation-pros.com/ignition/later.py) script module for some hints on how to handle this.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 22, 2020, 3:42pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/8 "2020-05-22T15:42:02Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 22, 2020, 4:42pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/9 "2020-05-22T16:42:06Z")

</div>

> [@paul-griffith](#):
>
> think there might be some way to bridge things in a generic way

Uhm? My `PythonAsJavaException` class?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 22, 2020, 4:43pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/10 "2020-05-22T16:43:11Z")

</div>

What, I’m supposed to _read_ these links you’re posting?! 😆

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 22, 2020, 4:49pm UTC](https://forum.inductiveautomation.com/t/a-universal-way-to-alert-devleopers-about-errors/34914/11 "2020-05-22T16:49:31Z")

</div>

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. /:
