"Constant/issue functions must only have a non empty base effort" after having migrated custom plugin to SQ 5.5 api

78 views
Skip to first unread message

Michel Pawlak

unread,
May 8, 2016, 4:08:05 AM5/8/16
to SonarQube
Hi,

I'm currently rewriting for SQ 5.5 a language plugin I wrote last summer for SQ 4.5.x (it was working fine util now). Since I migrated it to SQ I'm facing a strange issue with rules loading. 

I have a class that implements RulesDefinition. In its define method I :
  • first load rules into a NewRepository using a RulesDefinitionAnnotationLoader class
  • then for each rule key I retrieve the NewRule newRule from the repository by calling repository.rule(key), then call newRule.setDebtRemediationFunction(debtRemediationFunction) in order to set its DebtRemediationFunction.
  • in the end, I call repository.done()
The debtRemediationFunction is selected as follows:

            if (newRule != null) {

               newRule.setType(ruleType);

               DebtRemediationFunction debtRemediationFunction = null;

               switch (debtRemediationFunctionType) {

                   case CONSTANT_ISSUE:
                       
// (1)

                       debtRemediationFunction = newRule.debtRemediationFunctions()

                            .create(debtRemediationFunctionType, null, baseEffort);

                       break;

                   case LINEAR:

                       debtRemediationFunction = newRule.debtRemediationFunctions()

                           .create(debtRemediationFunctionType, multiplier, null);

                       break;

                   case LINEAR_OFFSET:

                       debtRemediationFunction = newRule.debtRemediationFunctions()

                           .create(debtRemediationFunctionType, multiplier, baseEffort);

                       break;

                   default:

                       LOGGER.warn("Unexpected debt remediation function type :'{}'", debtRemediationFunctionType);

                       break;

               }

               newRule.setDebtRemediationFunction(debtRemediationFunction);

           } else {

               LOGGER.error("Could not obtain new rule for key '{}'.", key);

           }



Currently I only have CONSTANT_ISSUE rules. The checks are visible in the UI (my interpretation is that the class is correctly considered as an extension point) I can select them and add them to profiles. And the code works fine @BatchSide , indeed my checks are executed by my sensor, prior to sensor execution I see that my RulesDefinition code is executed as well and logs dumping baseEffort and multiplier values show that the debtRemediationFunction is correctly set (i.e. baseEffort alway has a correct value, and multiplier is always null). Side note: debt remediation information is provided by the following custom annotation:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

public @interface DebtComputationMetadata {


   /**

    * {@link RuleType}

    *

    * @return {@link RuleType} as a String

    */

   RuleType ruleType();


   /**

    * {@link org.sonar.api.batch.debt.DebtRemediationFunction.Type} function to be used in order to compute debt.

    *

    * @return technical debt computation function

    */

   Type debtRemediationFunctionType();


   /**

    * Offset that defines the base effort debt of a SonarQube issue.

    *

    * @return debt remediation cost base effort

    */

   String remediationCostBaseEffort() default "";


   /**

    * Remediation cost multiplier.

    *

    * @return technical debt remediation cost multiplier

    */

   String remediationCostMultiplier() default "";


   /**

    * Effort to fix explanation.

    *

    * @return explanation

    */

   String effortToFixExplanation() default "";

}



However @ComputeEngineSide the analysis fails with the following message:

2016.05.07 13:35:40 ERROR [o.s.s.c.t.CeWorkerCallableImpl] Failed to execute task AVSLAGJWc8oz2a0OCp7w
java.lang.IllegalArgumentException: Constant/issue functions must only have a non empty base effort
	at org.sonar.api.internal.google.common.base.Preconditions.checkArgument(Preconditions.java:125) ~[sonar-plugin-api-5.5.jar:na]
	at org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction.validate(DefaultDebtRemediationFunction.java:108) ~[sonar-plugin-api-5.5.jar:na]
	at org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction.<init>(DefaultDebtRemediationFunction.java:44) ~[sonar-plugin-api-5.5.jar:na]
	at org.sonar.server.computation.issue.RuleImpl.effectiveRemediationFunction(RuleImpl.java:128) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.issue.RuleImpl.<init>(RuleImpl.java:53) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.issue.RuleRepositoryImpl.loadRulesFromDb(RuleRepositoryImpl.java:102) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.issue.RuleRepositoryImpl.ensureInitialized(RuleRepositoryImpl.java:91) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.issue.RuleRepositoryImpl.findByKey(RuleRepositoryImpl.java:62) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.step.LoadQualityProfilesStep$IsValid.apply(LoadQualityProfilesStep.java:70) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.step.LoadQualityProfilesStep$IsValid.apply(LoadQualityProfilesStep.java:67) ~[sonar-server-5.5.jar:na]
	at com.google.common.collect.Iterators$7.computeNext(Iterators.java:647) ~[guava-17.0.jar:na]
	at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143) ~[guava-17.0.jar:na]
	at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138) ~[guava-17.0.jar:na]
	at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:268) ~[guava-17.0.jar:na]
	at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:226) ~[guava-17.0.jar:na]
	at com.google.common.collect.FluentIterable.toList(FluentIterable.java:334) ~[guava-17.0.jar:na]
	at org.sonar.server.computation.step.LoadQualityProfilesStep.execute(LoadQualityProfilesStep.java:63) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.step.ComputationStepExecutor.executeSteps(ComputationStepExecutor.java:64) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.step.ComputationStepExecutor.execute(ComputationStepExecutor.java:52) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.taskprocessor.report.ReportTaskProcessor.process(ReportTaskProcessor.java:75) ~[sonar-server-5.5.jar:na]
	at org.sonar.server.computation.taskprocessor.CeWorkerCallableImpl.executeTask(CeWorkerCallableImpl.java:81) [sonar-server-5.5.jar:na]
	at org.sonar.server.computation.taskprocessor.CeWorkerCallableImpl.call(CeWorkerCallableImpl.java:56) [sonar-server-5.5.jar:na]
	at org.sonar.server.computation.taskprocessor.CeWorkerCallableImpl.call(CeWorkerCallableImpl.java:35) [sonar-server-5.5.jar:na]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_51]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_51]
	at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_51]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_51]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) [na:1.8.0_51]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_51]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_51]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_51]

The error message goes away (the analysis succeeds and issues are displayed in SQ's UI) if I comment the following line:

// (1)
debtRemediationFunction
= newRule.debtRemediationFunctions().create(debtRemediationFunctionType, null, baseEffort);


What's strange to me is the fact that If I add logs, I see that my RulesDefinition implementation seems never called @ComputeEngineSide. It is only called @BatchSide, I don't understand thus why commenting the above lines removes the failure. 

What am I doing wrong ? 

Thanks in advance,

Michel

Michel Pawlak

unread,
May 8, 2016, 4:26:03 AM5/8/16
to SonarQube
Note:

If I add LOGGER.info("key= '{}', baseEffort: '{}', multiplier: '{}'", key, baseEffort, multiplier.equals("") ? null : multiplier); in the code at position (1), then I get this in the logs when I start SQ:

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0000', baseEffort: '0min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0001', baseEffort: '20min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0002', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0003', baseEffort: '10min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0004', baseEffort: '10min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0005', baseEffort: '10min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0006', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0007', baseEffort: '10min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0008', baseEffort: '15min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0009', baseEffort: '15min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0010', baseEffort: '60min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0011', baseEffort: '3min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0012', baseEffort: '3min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0013', baseEffort: '3min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0014', baseEffort: '15min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0015', baseEffort: '60min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0016', baseEffort: '60min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0017', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0018', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0019', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0020', baseEffort: '10min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0021', baseEffort: '0min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0022', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0023', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0024', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0025', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0026', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0027', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0028', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0029', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0030', baseEffort: '5min', multiplier: 'null'

2016.05.08 10:16:00 INFO  web[c.q.p.s.m.a.r.AbstractLanaRulesDefinition] key= 'M0031', baseEffort: '5min', multiplier: 'null'


I really don't get why SQ considers then that the precondition "Constant/issue functions must only have a non empty base effort" is not met.

Michel 

Michel Pawlak

unread,
May 8, 2016, 4:46:03 AM5/8/16
to SonarQube
Ok I found the problem. It occurs when the baseEffort is set to 0 min. I have checks that have a INFO severity. I want INFO issues not to increase debt, how can I do it if I can't set base effort to 0min ?


Michel

On Sunday, May 8, 2016 at 10:08:05 AM UTC+2, Michel Pawlak wrote:

Scott B.

unread,
May 8, 2016, 2:27:19 PM5/8/16
to SonarQube
Hi Michel.

In that case, you don't need to call setDebtRemediationFunction. You can have rules without effort data, like this one.

Michel Pawlak

unread,
May 8, 2016, 5:44:37 PM5/8/16
to SonarQube
Hi Scott,

Indeed, thanks.

Michel

dum...@gmail.com

unread,
Jun 5, 2016, 1:39:55 AM6/5/16
to SonarQube
Hi ,

I upgrade from SQ 5.5 to  5.6, and i got this errors in processing task log. how i get it fixed ?

regards,
Johannes



On Sunday, May 8, 2016 at 10:08:05 AM UTC+2, Michel Pawlak wrote:
Reply all
Reply to author
Forward
0 new messages