How to manually parse the atlassian-jira-perf.log performance log from Jira

Platform Notice: Data Center Only - This article only applies to Atlassian products on the Data Center platform.

Note that this KB was created for the Data Center version of the product. Data Center KBs for non-Data-Center-specific features may also work for Server versions of the product, however they have not been tested. Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.

*Except Fisheye and Crucible

Summary

Jira writes several sets of performance data every minute to the atlassian-jira-perf.log. This how-to presents a way to manually parse this file into a timeline to get insights from it.

Environment

Jira Core 8.x

Jira's log4j.properties set to write the atlassian-jira-perf.log (default behavior)

Linux-like terminal (either native OS or Cygwyn) or Powershell

Solution

Linux

An easy way to parse the data into a timeline is using the command below (you may copy & paste it entirely):

1 2 3 4 5 6 7 8 TOKEN="currentThreadsBusy"; DATEPATTERN="2021-07-07"; egrep "^$DATEPATTERN.*?$TOKEN" atlassian-jira-perf.log | while read -r line ; do PERF_TIME=`echo $line | cut -d" " -f1,2 | sed -E 's/,[0-9]{3}//g'`; echo $line | egrep -o ''$TOKEN'"(,"value"){0,1}:"{0,1}[0-9]*"{0,1}' | while read -r linee; do PERF_VALUE=`echo $linee | sed 's/.*://g' | sed 's/"//g'`; echo "$PERF_TIME $PERF_VALUE"; done; done | awk '($3 > 0) {print}';

Just replace the example "currentThreadsBusy" above by the desired metric and the date pattern to another date or less restrictive like "2021", only.

Sample output

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 2021-07-07 20:59:46 3 2021-07-07 21:00:46 4 2021-07-07 21:01:46 14 2021-07-07 21:02:46 25 2021-07-07 21:03:46 43 2021-07-07 21:04:46 60 2021-07-07 21:05:46 4 2021-07-07 21:06:46 21 2021-07-07 21:07:46 58 2021-07-07 21:08:46 108 2021-07-07 21:09:46 114 2021-07-07 21:10:46 47 2021-07-07 21:11:46 17 2021-07-07 21:12:46 18 2021-07-07 21:13:46 9 2021-07-07 21:14:46 17 2021-07-07 21:15:46 5 2021-07-07 21:16:46 1

For currentThreadsBusy, the command will output each active Tomcat connector (as defined in <install-path>/conf/server.xml):

Sample output of 2 Tomcat connectors

1 2 3 4 5 6 7 8 2021-10-03 06:36:27 22 2021-10-03 06:36:27 0 2021-10-03 06:37:27 22 2021-10-03 06:37:27 0 2021-10-03 06:38:27 22 2021-10-03 06:38:27 0 2021-10-03 06:39:27 22 2021-10-03 06:39:27 0

Powershell

The equivalent command for Powershell for the Linux above is:

1 2 3 4 5 6 7 8 9 10 $TOKEN = "currentThreadsBusy" $file = "atlassian-jira-perf.log" $regex=[regex] ($TOKEN+'","value":(?<value>(\d|")+)') get-content $file | select -first 100 | foreach{ if($_ -match '^(?<date>(\d|-)+\s(\d|:)+).*\s(?<JSON>(\{|\[).*'+$TOKEN+'.*)') { ($regex.matches($matches.json).groups|?{$_.name -eq "value"}).value | foreach{ Write-Output ($matches.date+" "+$_.replace('"','')) } } }

Filtering peaks

In Linux, you may filter peaks by changing the awk comparison at the end of the command, replacing the Zero by whichever value you want:

1 awk '{if($3 > 0) print}'

So the command below will output only the moments with 100 or more busy Tomcat Threads:

1 2 3 4 5 6 7 8 TOKEN="currentThreadsBusy"; DATEPATTERN="2021-10-04"; egrep "^$DATEPATTERN.*?$TOKEN" atlassian-jira-perf.log | while read -r line ; do PERF_TIME=`echo $line | cut -d" " -f1,2 | sed -E 's/,[0-9]{3}//g'`; echo $line | egrep -o ''$TOKEN'"(,"value"){0,1}:"{0,1}[0-9]*"{0,1}' | while read -r linee; do PERF_VALUE=`echo $linee | sed 's/.*://g' | sed 's/"//g'`; echo "$PERF_TIME $PERF_VALUE"; done; done | awk '($3 > 100) {print}';

Example output

1 2 3 4 5 6 2021-10-04 09:03:46 106 2021-10-04 09:04:46 110 2021-10-04 09:05:46 113 2021-10-04 09:06:46 115 2021-10-04 09:07:46 140 2021-10-04 09:08:46 139

For Powershell, you might wish to add an additional if statement before the Write-Output command.

The command below will output only the moments with 100 or more busy Tomcat Threads:

1 2 3 4 5 6 7 8 9 10 11 12 $TOKEN = "currentThreadsBusy" $file = "atlassian-jira-perf.log" $regex=[regex] ($TOKEN+'","value":(?<value>(\d|")+)') get-content $file | select -first 100 | foreach{ if($_ -match '^(?<date>(\d|-)+\s(\d|:)+).*\s(?<JSON>(\{|\[).*'+$TOKEN+'.*)') { ($regex.matches($matches.json).groups|?{$_.name -eq "value"}).value | foreach{ if([int]($_.replace('"','')) -gt 100){ Write-Output ($matches.date+" "+$_.replace('"','')) } } } }

Useful metrics

Some commonly useful metrics are:

Metric

Description

Notes

currentThreadsBusy

Current number of active Tomcat HTTP Threads (user requests)

This value should top at the maxThreads declared in the server.xml connector.

If it gets close to or reaches such value, it's a clear indicator user requests are queueing up (Jira not being able to serve users in time).

If Tomcat's configured to have multiple connectors, the command above will output one line for each.

dbcp.numActive

Current number of active database connections

This value should top at the pool-max-size declared in the dbconfig.xml file.

If it gets close to or reaches such value, it's a hint that either the DB's performing under expectations or Jira's requesting more connections than currently configured, and Threads are queueing up for DB usage.

ProcessCpuLoad

Jira's process CPU load

Ranges from 0 to 1

SystemCpuLoad

The server or container CPU load

Ranges from 0 to 1

latencyNanos

The DB latency in nanoseconds

(1 ms = 1,000,000 nanos)

This should be as low as possible. You can learn the impact DB latency can have on several Jira operations on the article:

Database latency impact on Jira performance.

Note that the perf log's updated every 1 minute or so, and the data flushed into it is a snapshot from that exact moment.

Some metrics might've peaked in between the snapshots and the perf log won't show any of it.

Updated on April 8, 2025

Still need help?

The Atlassian Community is here for you.