Open neopaf opened 1 month ago
I guess, it's pretty simple option of GoogleScriptEngine, which costs next to nothing runtime. Maybe you'd turn it on by default (or provide some way to enable it)?
I don't have any knowledge of GoogleScriptEngine, and it isn't obvious how it helps from a quick Google search. Please feel free to submit a PR or provide more information. Thanks!
Thanks for quick reaction, Simon. I'm referring to object, obtained here https://github.com/structurizr/java/blob/d5e0d201e5fc9e1d6e6d4f3ea6d694e2706afbb0/structurizr-dsl/src/main/java/com/structurizr/dsl/ScriptDslContext.java#L47
Alas, I forgot how I did it like 5 years ago. But please consider changing this approach: https://github.com/structurizr/java/blob/d5e0d201e5fc9e1d6e6d4f3ea6d694e2706afbb0/structurizr-dsl/src/main/java/com/structurizr/dsl/ScriptDslContext.java#L73
Without name of file consequent stack trace (and IDE debugging) can not show file name (and open it in IDE, handle breakpoints), because runtime has no idea about original file name, and even if file was external (deployment.groovy
), it shows this (Script136.groovy
):
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:277)
at Script136$_run_closure2.doCall(Script136.groovy:15)
Let us start by passing eval
not string
, but Reader
, along these lines:
if(input is external)
engine.eval(new FileReader(scriptFile), bindings); // when input is external file; when
else
engine.eval(script.toString(), bindings); // as is
This will give proper file name to IDE and backtrace, hopefully enabling breakpoints and make life of script developers a tad bit happier?
I've pushed some changes (see https://github.com/structurizr/java/commit/ff37cc29fd4a9bfd9a79b669bae9406a95e1f750) ... but they only seem to work for Ruby unfortunately. If you have any further ideas, please let me know.
wow, that was fast, Simon. thanks for your effort. testing... will consider a bit deeper this weekend
For Googlers: take structurizr java, remove signing part from build.gradle
,
./gradlew publishToMavenLocal
Check out https://github.com/structurizr/lite, change structurizrVersion to 3.1.0,
./gradlew bootWar
#use build/libs/structurizr-lite.war
Simon, thanks a lot: I'm super happy now, breakpoints and stack filtering work now:
Maybe some stack trace sanitation would help, reading....
While IntelliJ IDEA manages to filter stack fine. Currently message has no line number where bad things in script happened:
Error
workspace.dsl: Error running script at deployment.groovy, caused by javax.script.ScriptException: javax.script.ScriptException: java.lang.reflect.UndeclaredThrowableException at line 711 of /Users/paf/Documents/Hermes/c4/./workspace.dsl: }
Neither do log files:
Name: PROD_MSK -> PROD/msk
javax.script.ScriptException: javax.script.ScriptException: java.lang.reflect.UndeclaredThrowableException
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:158)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:132)
at com.structurizr.dsl.ScriptDslContext.run(ScriptDslContext.java:70)
at com.structurizr.dsl.ExternalScriptDslContext.end(ExternalScriptDslContext.java:23)
at com.structurizr.dsl.StructurizrDslParser.endContext(StructurizrDslParser.java:1154)
at com.structurizr.dsl.StructurizrDslParser.parse(StructurizrDslParser.java:238)
at com.structurizr.dsl.StructurizrDslParser.parse(StructurizrDslParser.java:136)
at com.structurizr.lite.component.workspace.FileSystemWorkspaceComponentImpl.loadWorkspaceFromDsl(FileSystemWorkspaceComponentImpl.java:146)
at com.structurizr.lite.component.workspace.FileSystemWorkspaceComponentImpl.loadWorkspace(FileSystemWorkspaceComponentImpl.java:113)
at com.structurizr.lite.component.workspace.FileSystemWorkspaceComponentImpl.getWorkspace(FileSystemWorkspaceComponentImpl.java:203)
at com.structurizr.lite.web.ApiController.getWorkspace(ApiController.java:37)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:384)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:905)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: javax.script.ScriptException: java.lang.reflect.UndeclaredThrowableException
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:155)
... 62 more
Caused by: java.lang.reflect.UndeclaredThrowableException
at jdk.proxy1/jdk.proxy1.$Proxy84.accept(Unknown Source)
at java.base/java.lang.Iterable.forEach(Iterable.java:75)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:48)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap.invoke(PojoMetaMethodSite.java:198)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:51)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
at deployment.run(deployment.groovy:8)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317)
... 63 more
Caused by: java.lang.Exception: Exception while handling {{struct}} in relation[{1812 | vrf SIG | } ---[Diameter Gy запросы]---> {1839 | mn-hmsfe | }]
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:72)
at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:59)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrap.callConstructor(ConstructorSite.java:84)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:286)
at deployment$_run_closure2.doCall(deployment.groovy:22)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:107)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:323)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:274)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1030)
at groovy.lang.Closure.call(Closure.java:427)
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:50)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:112)
... 75 more
Caused by: java.lang.Exception: For DeploymentEnvironment[PROD_MSK] did not find inventory, please check deployment.groovy parameters
at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:72)
at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:59)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrap.callConstructor(ConstructorSite.java:84)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:59)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:277)
at deployment$_run_closure2.doCall(deployment.groovy:15)
... 84 more
2024-09-28T09:06:59.536+03:00 ERROR
I guess, most interesting lines with .groovy file line on them got hidden under ".... N more" cuts.
Not sure how to handle that properly. Googling gives this: https://stackoverflow.com/questions/6259202/how-do-i-print-a-groovy-stack-trace
Not sure how to do that in properly, since you don't really know about Groovy implementation details under the ScriptEngine's hood.
Maybe just simple call would work, since we know that GroovyScriptEngine is on your class path. And it removes only groovy implementation calls, not affecting any other language. So I assume it is save to call it. Prior to printing error messages to log/ui.
Just call this one methods around exception to cleanup stack trace. https://docs.groovy-lang.org/latest/html/gapi/org/codehaus/groovy/runtime/StackTraceUtils.html#sanitize(java.lang.Throwable)
Hopefully this would reach all targets...
Description
Currently scripts have no file name in debug info, so when I'm trying to debug them I get no breakpoints and no stepping around.
Priority
I have no budget and there's no rush, please add this feature for free
More information
Workaround: breakpoint in some lib method, like System.println and inspect whatever passed in there:
(This is much faster than reading tons of manuals/sources sometimes, for some people)
Yet, it would be easier still if that debug info would've been provided. I guess, it's pretty simple option of GoogleScriptEngine, which costs next to nothing runtime. Maybe you'd turn it on by default (or provide some way to enable it)?