Reporting: Logging does not work inside chart script

I was trying to add an IntervalMarker to a chart in a report and move that to the background layer. I was having some difficulty. I think exceptions get captured and silently discarded in those scripts. After adding some of the usual system logger calls (system.util.getLogger), I found those do work there. Nothing shows up in the log page. I even tried plain old print statements, hoping they would wind up in the wrapper.log file, but got nothing. I finally had to make system.file.writeFile calls to a temporary file to get any output.

Show your code. Jython doesn't catch java errors in try: − except Exception, e: constructs.

My now-working script looks like this:

def configureChart(data, chart):
	from org.jfree.chart.renderer.xy import XYStepRenderer
	from org.jfree.chart.plot import IntervalMarker
	from org.jfree.ui import Layer
	from java.awt import BasicStroke, Color
	
	plot = chart.getPlot()
	renderer = XYStepRenderer()
	renderer.setStroke(BasicStroke(2.0))
	renderer.setSeriesPaint(0, Color.decode("#4269D0"))
	plot.setRenderer(0, renderer)
	
	logger = system.util.getLogger("chart")
	logger.error("No error, starting chart")
	markerStart = data["waterAddedData"]["fillStartTime"].getTime()
	markerEnd = data["waterAddedData"]["fillEndTime"].getTime()
	intervalMarker = IntervalMarker(markerStart, markerEnd)
	intervalMarker.setPaint(Color.decode("#CCCCCC"))
	plot.addDomainMarker(intervalMarker, Layer.BACKGROUND)

Even using the error level, nothing gets put into the logs. No logger named "chart" appears in the list of loggers.

My original problem was using from org.jfree.chart.ui import Layer, but it looks like Ignition is using the 1.0 branch of JFreeChart, where Layer is in org.jfree.ui. It never occurred to me to put the import statements inside the try block (legal in Jython, not legal in Java), so there was probably an uncaught exception being raised, but it isn't visible anywhere in the Designer or the logs

  1. Move your code to a project library script, and move all imports outside the def, along with the creation of the logger object (so it is persistent).

  2. In the first line inside the def, invoke the logger.

  3. Ideally, nest all the rest of the code in a double-except try: construct, so you can log both java and jython errors. Something like this:

Report errors at design time are raised and caught in the designer, so they show up in the output console:

If you actually run the report on the gateway, e.g. by executing a schedule directly, you get an error in the logs:

To preempt a possible question - errors in the designer are not raised more visibly because report generation is being run directly on the painting thread - the report preview is a live preview using Swing objects. If we raised those errors to ErrorUtil, you'd be getting a constant flood of errors as repaint operations run and cause your chart(s) with issues to run their repaint methods that are broken.

This is the answer. I don't know why I didn't think to check the output console.