Groovy, STS, and debug info, information, or symbols - grails

I'm trying to include the debug information or symbols in my Groovy code so that I can use the Spring Security annotations with SpEL to access an annotated method's arguments by name. For example:
#PreAuthorize("hasPermission(#id, 'View')")
public void doSomething(Integer id)
{
....
}
Everything works fine when I use the STS 'run-test' command, which uses the Groovy RunTest script. By that I mean I can access a method's argument by name. However, whenever I try to use the 'run-app' command, the debug information is not included.
I looked at the RunTest script and the script explicitly calls the Java Compiler with the debug option set to true.
How can I enable debug information for my development and production environments? Do I need to modify the Groovy script to call the Java compiler on the Groovy code or is there any easier way?

Never found an elegant solution to this. Instead I just used filters as the parameters that were being passed to my methods were being extracted from the URL by Grails.

Related

Set Quarkus Logging Category Level via Environment Variables

In Spring, it is possible to set the Logging Category Level via environment variables. I've tried the same in a Quarkus application with the following logger declaration:
package org.my.group.resteasyjackson;
public class JacksonResource {
private static final Logger LOGGER = LoggerFactory.getLogger(JacksonResource.class);
#GET
public Set<Quark> list() {
LOGGER.info("Hello");
return quarks;
}
}
Executing the build artifact with
QUARKUS_LOG_CATEGORY_ORG_MY_LEVEL=WARN java -jar my-artifactId-my-version-runner.jar
will log anything at info level (since it is the default), therefore the "Hello" message.
However, inserting
quarkus.log.category."org.my".level=WARN
in the application.properties file works as desired. Are environment variables in this use case not usable for Quarkus applications?
Just tried with quarkus 1.13.1 and adding extra underscores for the quotes seems to work, try:
QUARKUS_LOG_CATEGORY__ORG_MY__LEVEL=WARN
You can do this:
quarkus.log.category."org.my".level=${LOG_LVL:INFO}
This simply means: use the log-level from my env variable "LOG_LVL" and if this is not present use INFO as default.
You can set this variable either as an env.variable or pass it through as system parameter during startup, but I'm not sure about the syntax as system parameter.
You should be able to use a system property (!= environment variable) like this:
java -Dquarkus.log.category.\"org.my\".level=WARN ...
Note: system properties will overrwite their application.properties, except for a quarkus.profile due to a bug.
No idea if environment variables can overwrite them too. Maybe the " need to be escaped. (I find environment variables brittle, I prefer system properties.)

Can a workflow step access environment variables provided by an EnvironmentContributingAction?

A custom plugin we wrote for an older version of Jenkins uses an EnvironmentContributingAction to provide environment variables to the execution so they could be used in future build steps and passed as parameters to downstream jobs.
While attempting to convert our build to workflow, I'm having trouble accessing these variables:
node {
// this step queries an API and puts the results in
// environment variables called FE1|BE1_INTERNAL_ADDRESS
step([$class: 'SomeClass', parameter: foo])
// this ends up echoing 'null and null'
echo "${env.FE1_INTERNAL_ADDRESS} and ${env.BE1_INTERNAL_ADDRESS}"
}
Is there a way to access the environment variable that was injected? Do I have to convert this functionality to a build wrapper instead?
EnvironmentContributingAction is currently limited to AbstractBuilds, which WorkflowRuns are not, so pending JENKINS-29537 which I just filed, your plugin would need to be modified somehow. Options include:
Have the builder add a plain Action instead, then register an EnvironmentContributor whose buildEnvironmentFor(Run, …) checks for its presence using Run.getAction(Class).
Switch to a SimpleBuildWrapper which defines the environment variables within a scope, then invoke it from Workflow using the wrap step.
Depend on workflow-step-api and define a custom Workflow Step with comparable functionality but directly returning a List<String> or whatever makes sense in your context. (code sample)
Since PR-2975 is merged, you are able to use new interface:
void buildEnvVars(#Nonnull Run<?, ?> run, #Nonnull EnvVars env, #CheckForNull Node node)
It will be used by old type of builds as well.

how to debug this lithium request?

I am trying to work on whats wrong with my lithium current setup. I have installed the Xdebug and verified that remote host can establish the connection as requested.
http://myinstance.com/test/lithium/tests/cases/analysis/logger/adapter/CacheTest?filters[]=lithium\test\filter\Coverage
Please note in fresh installation in local environment , "Coverage" Filter is working as expected.
I added some test code inside the "apply" function in coverage.php but it is not even called !!!! Can some have experience in debugging the above URL ?
I am not able to understand why coverage filter is not called up and executed ...Any hints are highly appreciated !
The filters in the query string are added to the options in lithium\test\Controller::__invoke() and then passed into the test Report object created by the test Dispatcher. The Report object finds the test filter class and then runs the applyFilter() method for that test filter as can be seen in lines 140 to 143 of the current code. So those lines would be another place to debug. Those should wrap the run() method of your tests with this filter code inside the apply() method that uses xdebug_get_code_coverage() and related functions. You said you added test code in the apply method and it isn't called. I'm not sure what the issue is. Are you sure you are pointing to the right server and code location? It is possible to run tests from the command line. Maybe you should try that. See code comments in lithium\console\command\Test or run li3 test --help for info on how to use the command-line test runner.
I can confirm on nginx I also have /test/lithium/tests/cases/analysis/logger/adapter/CacheTest?filters[]=lithium\x5Ctest\x5Cfilter\x5CCoverage in my access log. The \x5C is expected url encoding of the backslash character.

Add logging to an external pluggable script

As described in Can't call one closure from another, I am using a pluggable script from within a Grails app.
Unfortunately, I've found that I can't use log4j from within these scripts. I am forced to use println.
I tried using
import org.apache.commons.logging.LogFactory
def Log log = LogFactory.getLog(getClass())
but I got no output. When I print out the result of the call to getClass(), I get something like
myscript$_run_closure5
So I'm thinking the issue is that there is no configuration in my Grails Config.groovy file for this class.
Is there a way for me to programmatically add these pluggable scripts to the log4j configuration? Keep in mind that I do not know in advance what the names of the scripts are, so this has to happen at runtime.
Consider the following code:
import org.apache.log4j.Logger
// ...
Logger log = Logger.getLogger('MyPlugin')
new File( grailsApplication.config.externalFiles ).eachFile { file ->
Binding binding = new Binding()
binding.variables.log = log
GroovyShell shell = new GroovyShell(binding)
shell.evaluate(file)
strategies.put( binding.variables.key, binding.variables )
}
Explanation:
It is not obligatory to pass class name to getLogger, it can be actually any string. You just need to make sure that this string is matched in log4j.properties of the main program.
You pass once created log to plugin scripts via binding variable "log". Then plugin scripts can access it simply as log.info('test123')
My personal recommendation would be to use logback instead of log4j. Both libraries were developed by the same guy and it is stated that logback supersedes log4j.

Does Grails surround log statements with isSomethingEnabled()

As per http://docs.codehaus.org/display/GROOVY/Groovy+1.8+release+notes#Groovy18releasenotes-Log groovy does surround log statements with checks like isDebugEnabled() etc.
Does grails do that for the generated code?
For this log call in a grails service:
log.debug("competitors errors stage 1: ${failedCarrierRequests}")
In the decompiled .class file I see only this:
arrayOfCallSite[85].call(log, new GStringImpl(new Object[] { allCompetitorDepartmentsRows.get() }, new String[] { "All competitors: ", "" }));
It is unclear whether there is a check for log level behind the scenes or not.
As of 2.2.2: no.
Grails injects an apache commons Log field into the artefact classes, and the log4j plugin marries that to a log4j Logger.
However, in your example you pass a GString as the only parameter. Since they are lazy-transformed to Java Strings, the log4j logger would hit it's own internal debug enabled check and skip the toString() call.
If you do something expensive like parameter building, however, and you're concerned about the wasted cycles, you must call isDebugEnabled() yourself:
if (log.isDebugEnabled()) {
log.debug("Some string concatenation with a slow method: " + slowMethod())
}
I should point out that this contrived example could be converted to use GString to save the debug check:
log.debug "GString with lazily initialized slow method call: ${slowMethod()}"
There was some discussion awhile back on the grails-user mailing list about adding an AST transformation to add the checks, but it didn't go anywhere.
Okay response that GStrings are lazy loaded doesn't seems to hold up against my testing.
I have created a test to basically log something four different ways, and it does appear to evaluate any logging statement GString.
Here is my test file GIST: https://gist.github.com/tgsoverly/34f9a56287291297777b
The test fails for the GString and the method IS called when in the log statement.
It would also not be something the groovy people say should be the case according to their template section: http://groovy.codehaus.org/Strings+and+GString

Resources