In order to populate the gateway log webpage I am sure there has to be some builtin method for parsing the first wrapper.log
file into a easier data structure than the pure text file.
I am curious if its exposed and I can get to it in scripting?
In order to populate the gateway log webpage I am sure there has to be some builtin method for parsing the first wrapper.log
file into a easier data structure than the pure text file.
I am curious if its exposed and I can get to it in scripting?
The webpage just uses the system_logs.idb file; it doesn’t know or care about the wrapper log. It should be possible to configure logback to send everything (including stdout) to a file or other buffer in a format you know how to parse.
Kindling also has some code you could follow to parse Ignition’s standard wrapper log formatting.
Ah, I started going the approach of hitting the http://localhost/data/status/logs
endpoint, but was struggling with getting a JSESSIONID
. Any ideas on how to get that with the builtin Ignition IDP enabled?
In regards to configuring logback, you can actually configure it to push straight into a database as well with a database appender. I am just looking for something to hit the internal logs directly through a project script.
Is there any reason you would say to go with the approach of parsing the wrapper log vs the logs endpoint? Other than the fact that's probably an implementation detail lol
Parsing the wrapper log will get you more events (technically: all stdout
and stderr
logging from the Gateway process; practically: any bare print
statements in gateway scoped scripts); however, you also face other restrictions with e.g. logger names (unless you change the formatting and write your own parsing logic). It’s really a tradeoff.
If you’re inside of Ignition already in a scripting context, you could skip the API endpoint and go directly to the ‘source’ - GatewayContext defines getLoggingManager
, which returns a… GatewayLoggingManager
, which defines queryLogEvents()
.
It looks like getLoggingManager
is expecting an argument, but the javadocs only show a version with no args.
Is there potentially something I have wrong here? (Executing on a perspective button to ensure scope)
from com.inductiveautomation.ignition.gateway.model import GatewayContext
loggingManager = GatewayContext.getLoggingManager()
system.perspective.print(loggingManager)
07:28:45.009 [AWT-EventQueue-0] ERROR com.inductiveautomation.ignition.client.util.gui.ErrorUtil - Error running action 'dom.onClick' on Test@D/root/Icon: Traceback (most recent call last):
File "<function:runAction>", line 4, in runAction
TypeError: getLoggingManager(): expected 1 args; got 0
com.inductiveautomation.ignition.common.GenericTransferrableException: Traceback (most recent call last):
File "<function:runAction>", line 4, in runAction
TypeError: getLoggingManager(): expected 1 args; got 0
at org.python.core.Py.TypeError(Py.java:236)
at org.python.core.PyReflectedFunction.throwError(PyReflectedFunction.java:213)
at org.python.core.PyReflectedFunction.throwArgCountError(PyReflectedFunction.java:266)
at org.python.core.PyReflectedFunction.throwError(PyReflectedFunction.java:323)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:171)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:208)
at org.python.core.PyObject.__call__(PyObject.java:446)
at org.python.core.PyObject.__call__(PyObject.java:450)
at org.python.pycode._pyx110.runAction$1(<function:runAction>:6)
at org.python.pycode._pyx110.call_function(<function:runAction>)
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyFunction.function___call__(PyFunction.java:474)
at org.python.core.PyFunction.__call__(PyFunction.java:469)
at org.python.core.PyFunction.__call__(PyFunction.java:464)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:839)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:821)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:828)
at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:1002)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:893)
at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:147)
at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:74)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:263)
at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:252)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:221)
at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at com.inductiveautomation.perspective.gateway.threading.BlockingWork$BlockingWorkRunnable.run(BlockingWork.java:58)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: com.inductiveautomation.ignition.common.GenericTransferrableException: TypeError: getLoggingManager(): expected 1 args; got 0
... 33 common frames omitted
You need an instance of GatewayContext. Easiest way to do that is the IgnitionGateway.get()
snippet that’s floating around on the forums.
Ahh, that does the trick.
from com.inductiveautomation.ignition.gateway import IgnitionGateway
from com.inductiveautomation.ignition.common.logging import LogQueryConfig
loggingManager = IgnitionGateway.get().getLoggingManager()
queryFilter = LogQueryConfig.newBuilder().build()
logResults = loggingManager.queryLogEvents(queryFilter)
events = logResults.getEvents()
system.perspective.print(events)
I did notice this documentation error for the LogQueryConfig it states the following:
A set of parameters for querying the logging system. Can be created by hand, or with LogQueryConfigBuilder.newBuilder() (the preferred method)
But it seems that the newBuilder
method isn't valid for LogQueryConfigBuilder, instead it should be LogQueryConfig.newBuilder()