One of the challenges that Jira admins face is monitoring the health of their Jira instance. While there are some built-in tools for doing this, it’s useful to know how to perform routine maintenance using ScriptRunner.
One such routine maintenance task is the monitoring of Jira Project sizes. There’s no direct method or way of doing this; instead we get all of the issues for a given project, and sum up the size of the attachments on each issue. In this way, we get an idea of which Jira Projects are becoming unwieldy.
The code required to perform this calculation isn’t complicated. However, if the script runs too long it’ll simply time out. This is especially true if you’re calculating the size of multiple Projects. Here’s the code to calculate the size of a single project:
import org.ofbiz.core.entity.GenericValue;
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.project.ProjectManager
def totalSize = 0
def attachmentManager = ComponentAccessor.getAttachmentManager()
ProjectManager projectManager = ComponentAccessor.getProjectManager()
def projectName = "<projectName>"
Project proj = projectManager.getProjectByCurrentKey(projectName)
IssueManager issueManager = ComponentAccessor.getIssueManager()
for (GenericValue issueValue: issueManager.getProjectIssues(proj.genericValue)) {
Issue issue = issueManager.getIssueObject(issueValue.id)
attachmentManager.getAttachments(issue).each {
attachment ->
totalSize += attachment.filesize
}
}
log.warn("Total size of attachments for ${proj.name} is ${totalSize / 1024} kb")
This code works, but makes no provisions for especially large projects that would cause the script to time out. This would easily be exacerbated if more than one project were being analyzed. So how do we solve this?
As we’ve previously discussed, Jira has a number of methods that allow for asynchronous operations. The code below performs the same basic operation as the previous script, but it submits each operation to the executor. This allows for multiple projects to be analyzed simultaneously. Additionally, by changing the value of the awaitTermination method, we can actually change how long the script will run before it times out.
import org.ofbiz.core.entity.GenericValue;
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.project.ProjectManager
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
def attachmentManager = ComponentAccessor.getAttachmentManager()
ProjectManager projectManager = ComponentAccessor.getProjectManager()
def projects = [<projects>]
def totalSize = 0
log.warn("There should be ${projects.size()} results when this fininshes.")
//Log the number of projects in the list, so you can easily tell if it finished or simply timed out
// Create a fixed thread pool with a number of threads equal to the size of the list of projects
ExecutorService executor = Executors.newFixedThreadPool(projects.size());
// Create a list of tasks to execute
List < Runnable > tasks = []
projects.each { project ->
//Iterate through the list of projects
Project proj = projectManager.getProjectByCurrentKey(project)
IssueManager issueManager = ComponentAccessor.getIssueManager()
tasks.add({
for (GenericValue issueValue: issueManager.getProjectIssues(proj.genericValue)) {
Issue issue = issueManager.getIssueObject(issueValue.id)
attachmentManager.getAttachments(issue).each {
attachment ->
totalSize += attachment.filesize
}
}
log.warn("Total size of attachments for ${proj.name} is ${totalSize / 1024} kb")
})
}
// Submit the list of Tasks to the executor
tasks.each {
task ->
executor.submit(task)
}
//Stop the Executor, and wait for all of the running tasks to finish
executor.shutdown()
executor.awaitTermination(10, TimeUnit.MINUTES)
Leave a Reply