Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Next challenges

Recent achievements

  • Global
  • Personal

Recognition

  • Give kudos
  • Received
  • Given

Leaderboard

  • Global

Trophy case

Kudos (beta program)

Kudos logo

You've been invited into the Kudos (beta program) private group. Chat with others in the program, or give feedback to Atlassian.

View group

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Limit the impact of an expensive scripted field (script runner) Edited

Hi everyone,

due to the lack of a documented Tempo Timesheets Java API i have created a script runner scripted field that sums up the Tempo field "Billed Time" for an issue using the Tempo Rest API.

This script runs over 100ms when the field is rendered.

This sounds to me like it has the potential for a heavy performance impact.

So i removed it's searcher, restricted the field to a more narrow context and kept it out of any screens.

But the business use case doesnt allow to narrow down the context very far this still feels insufficient,

i can for example see the field is rendered when an app finds a corresponding issue in /rest/api/2/search or someone comments an issue.

Does anyone have a creative idea to restrict the performance impact any further?

How did you guys solve similar problems?

Cheers

Jens

 

4 answers

Hi Jens,

I am not an expert in Scriptrunner but maybe you can use something in this direction:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.worklog.Worklog
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.tempoplugin.core.workattribute.api.WorkAttributeService
import com.tempoplugin.core.workattribute.api.WorkAttributeValueService

@WithPlugin("is.origo.jira.tempo-plugin")

@PluginModule
WorkAttributeService workAttributeService

@PluginModule
WorkAttributeValueService workAttributeValueService

def worklogManager = ComponentAccessor.worklogManager

def worklogs = worklogManager.getByIssue(issue)

def attribute = workAttributeService.getWorkAttributeByKey("Tempo.WorklogBilledHours").returnedValue

worklogs.sum { Worklog worklog ->
workAttributeValueService.getWorkAttributeValueByWorklogAndWorkAttribute(worklog.id, attribute.id).returnedValue
} as Long

Hi Alexander.

thanks that looks awesome.

I will try this out.

You should put that in your public docs if it isnt.

Would also make a nice contribution to the adaptavist libary.

Good Luck for your webinar with Andreas today!

kind regards

Jens

Jens,

will do once you confirmed that it is working (and how). 

Keep us posted!

BR

Hi Alexander, 
i cant get the last few lines to work,

the return value of 

workAttributeValueService.getWorkAttributeValueByWorklogAndWorkAttribute(worklog.id, attribute.id).returnedValue

 

seems to be a
com.tempoplugin.core.workattribute.api.WorkAttributeValue
and i don't know how to access the number of billed time on that object.

 

Any clues?

kind regards

Jens

Jens,

a hint would be:

getValue()

BR 

Alexander,
that hint was helpful. 
I've slighty rewritten the end of the script to fall back to the logged time if the billed time is empty and the working version looks like this:

def attribute = workAttributeService.getWorkAttributeByKey("Tempo.WorklogBilledHours").returnedValue
Long sum = 0L

Iterator wlIterator = worklogs.iterator()
while (wlIterator.hasNext()) {
Worklog worklog = wlIterator.next()
def value = workAttributeValueService.getWorkAttributeValueByWorklogAndWorkAttribute(worklog.id, attribute.id).returnedValue

if (value != null) {
Long longValue = Long.parseLong(value.getValue())
sum += longValue
} else {
log.error worklog.getTimeSpent()
sum += worklog.getTimeSpent()
}
}
0 votes

Cache the sum (I don't know where to store) and recalculate only if the issue's update date changes?

Yeah thats one option i was considering, i'd make a static groovy class and use that one as a cache.

Cheers

Jens

@Alexander Eck , thanks a lot for your helpful input.

You dont happen to have a similar script ready that allows me to extract expenses via the Java API?

Have a nice weekend.

Hi Jens,

no not really. Maybe you can try:


import com.tempoplugin.core.expense.api.Expense;
import com.tempoplugin.core.expense.api.ExpenseService;

getExpensesByScope(@Nonnull ScopeType scopeType, Long... scope)
getExpensesByScopeAndDate(Pair<LocalDate, LocalDate> duration, Expense.ScopeType scopeType, Long... scope)

with ScopeType = ISSUE.

You might also take a look at the REST API documentation.

Have a good one.

BR

Like Jens Kisters _APTIS_ likes this

@Alexander Eck thanks for your input again!

We are now looking to do the same for the planned time, do you happen to have a Java code snippet for that as well?

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Posted in Jira Software

Presenting the "Best of 2020" Jira Software roundup!

Catch up with Atlassian Product Managers in our 2020 Demo Den round-up! From Advanced Roadmaps to Code in Jira to Next-Gen Workflows, check out the videos below to help up-level your work in the new ...

7,143 views 8 28
Join discussion

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you