How to add the missing Sub-task burndown chart to JIRA Software
I am using Atlassian JIRA Software in most of my projects. But I am always using hand drawn burndown charts like this one:
But why? There are several options for burndown charts available within JIRA Software! Yes that’s true, but:
- Personally I don’t like booking times on tickets. For me it is a waste of time if developers have to think about if it were 2hours or 2,5hours! So a time based burndown is not helping me.
- Next there is this Story Point burndown chart. Also a great idea but in real-life, where most of the stories are closed at the end of a Sprint, that also won’t help me much.
- Ok fine. Then lets go with this issue count option. Also a great idea but there is one constraint: it is only counting parent issues – not the Sub-task. Me and my team are heavily using Sub-tasks and they should definitely be included in my burndown.
How to get a Sub-task based burndown chart?
Keep in mind: it is working for us, but before using it in production you should definitely invest some time to test and make it stably running in your own environment!
- You need to have the Script Runner Plugin installed within your JIRA Software instance. That plugin is charged after a 30 days trial!
- Create a custom number field available for all projects where you want to use this kind of Sub-task burndown. I named it “Open Issues Counter”.
- Set your JIRA Software Board to use that custom field for estimation.
- Add the following content to a file OpenIssuesCounter.groovy and put it into your JIRA_HOME/scripts directory
Edit 29.11.2019: Updated source code to fix breaking changes in Jira 8.0. (Stefan)
Java1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950import com.atlassian.jira.bc.issue.search.SearchServiceimport com.atlassian.jira.component.ComponentAccessorimport com.atlassian.jira.event.type.EventDispatchOptionimport com.atlassian.jira.issue.CustomFieldManagerimport com.atlassian.jira.issue.IssueManagerimport com.atlassian.jira.issue.MutableIssueimport com.atlassian.jira.issue.search.SearchResultsimport com.atlassian.jira.jql.parser.JqlQueryParserimport com.atlassian.jira.security.JiraAuthenticationContextimport com.atlassian.jira.user.ApplicationUserimport com.atlassian.jira.user.util.UserManagerimport com.atlassian.jira.web.bean.PagerFilterimport com.atlassian.query.Queryimport org.apache.log4j.Levelimport org.apache.log4j.LoggerJqlQueryParser jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)SearchService searchService = ComponentAccessor.getComponent(SearchService)IssueManager issueManager = ComponentAccessor.getIssueManager()CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager()JiraAuthenticationContext jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext()UserManager userManager = ComponentAccessor.getUserManager()ApplicationUser user = userManager.getUserByName("dm")jiraAuthenticationContext.setLoggedInUser(user)Logger log = Logger.getLogger("net.novatec.OpenIssuesCounter")Query query = jqlQueryParser.parseQuery("project = bur and Sprint in openSprints() and issuetype in standardIssueTypes()")SearchResults results = searchService.search(user, query, PagerFilter.getUnlimitedFilter())log.setLevel(Level.DEBUG)MutableIssue issuelog.debug "found and processing ${results.getResults().size()} issues now!"results.getResults().each {issue = issueManager.getIssueObject(it.id)int counter = 0if (it.subTaskObjects) {counter = issue.subTaskObjects.findAll { !it.resolutionDate }.size()} else {counter = (it.resolutionDate) ? 0 : 1}issue.setCustomFieldValue(customFieldManager.getCustomFieldObjectByName("Open Issues Counter"), (Double) counter)issueManager.updateIssue(user, issue, EventDispatchOption.DO_NOT_DISPATCH, false)}log.debug "... finished!"- Change line 24 to match the username to your desired user. The script will make the modifications with that username!
- Change line 27 to match your JIRA Software project(s).
- Change line 41 to match the name of your custom field if it is not “Open Issues Counter”.
- Add a Service in JIRA to execute this script. Navigate to System -> Services.
- Name:Open Issues Counter
- Class: com.onresolve.jira.groovy.GroovyService
- Schedule: Advanced
- Expression: 0 0/5 * * * ? *
- That will execute the script every 5 minutes. Just change it to your needs.
- Click Add
- admin.service.jelly.input: OpenIssuesCounter.groovy
- Use the filename you have chosen in step 4.
- Click Update
What is it doing and how does it work?
The script will be executed every 5 minutes and modify the value of the custom field “Open Issues Counter” for every issue within the current sprints of your given projects. If it is a Sub-task it will get a 0. If it is a parent task that has no Sub-tasks it will get a 1. If it is a parent task that has Sub-Tasks it will get a number telling how many open Sub-tasks it has plus the parent task itself.
Based on these values you will have a burndown based on the issue count including your Sub-tasks.
Let me know if that helped you, if there are better ways or if it is not working as expected.
-Dirk
Edit 18.08.2017: Big thanks to our NovaTec software craftsman community (especially Daniel Bednorz) for refactoring the source code!
Comment article
Recent posts






Comments
Klaus Steigmiller
Hi Dirk,
thanks for your good idea and your artice.
The calculation of the first counter may have 2 mistakes
int counter = (!it.subTaskObjects && it.resolutionDate) ? 0 : 1
1. Subtasks with no resolution will get “1” and not “0”, so you count them twice
2. Closed parent issues with subtasks will never get “0” even if all subtask are closed.
Why update subtasks if you don’t want to count them?
With ‘issuetype in standardIssueTypes()’ in the jql query subtasks are exclude.
kind regards Klaus
Guilherme
Hello Angela!
Did you get it to work on Jira Cloud?
Dirk Maucher
Hi Angela, as Script Runner is supported on JIRA Cloud it should work with smaller modifications. But to be honest: never tried it with JIRA Cloud. You can leave me a message at dirk.maucher@novatec-gmbh.de to see how we can proceed on that. Best, Dirk
Angela Alston-Roberts
How can you make this work for Jira Cloud?