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 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 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: |
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.
Was this helpful?