javacore-analyser 2.1rc5__py3-none-any.whl → 2.2rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- javacore_analyser/__main__.py +43 -0
- javacore_analyser/data/html/error.html +22 -0
- javacore_analyser/data/jquery/theme.blue.css +9 -3
- javacore_analyser/data/jquery/wait2scripts.js +4 -2
- javacore_analyser/data/style.css +32 -0
- javacore_analyser/data/xml/report.xsl +167 -20
- javacore_analyser/har_file.py +65 -0
- javacore_analyser/javacore_analyser_batch.py +29 -11
- javacore_analyser/javacore_analyser_web.py +7 -3
- javacore_analyser/javacore_set.py +19 -2
- javacore_analyser/verbose_gc.py +0 -1
- {javacore_analyser-2.1rc5.dist-info → javacore_analyser-2.2rc1.dist-info}/METADATA +26 -9
- {javacore_analyser-2.1rc5.dist-info → javacore_analyser-2.2rc1.dist-info}/RECORD +16 -13
- {javacore_analyser-2.1rc5.dist-info → javacore_analyser-2.2rc1.dist-info}/WHEEL +0 -0
- {javacore_analyser-2.1rc5.dist-info → javacore_analyser-2.2rc1.dist-info}/entry_points.txt +0 -0
- {javacore_analyser-2.1rc5.dist-info → javacore_analyser-2.2rc1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
#
|
2
|
+
# Copyright IBM Corp. 2024 - 2024
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
#
|
5
|
+
import argparse
|
6
|
+
|
7
|
+
from javacore_analyser import javacore_analyser_batch, constants, javacore_analyser_web
|
8
|
+
|
9
|
+
|
10
|
+
def main():
|
11
|
+
parser = argparse.ArgumentParser(prog="python -m javacore_analyser")
|
12
|
+
subparsers = parser.add_subparsers(dest="type", help="Application type", required=True)
|
13
|
+
|
14
|
+
batch = subparsers.add_parser("batch", description="Run batch application")
|
15
|
+
batch.add_argument("input", help="Input file(s) or directory")
|
16
|
+
batch.add_argument("output", help="Destination report directory")
|
17
|
+
batch.add_argument("--separator", default=constants.DEFAULT_FILE_DELIMITER)
|
18
|
+
|
19
|
+
web = subparsers.add_parser("web", description="Run web application")
|
20
|
+
web.add_argument("--debug", help="Debug mode. Use True only for app development", default=False)
|
21
|
+
web.add_argument("--port", help="Application port", default=constants.DEFAULT_PORT)
|
22
|
+
web.add_argument("--reports-dir", help="Directory to store reports data",
|
23
|
+
default=constants.DEFAULT_REPORTS_DIR)
|
24
|
+
|
25
|
+
args = parser.parse_args()
|
26
|
+
|
27
|
+
app_type: str = args.type
|
28
|
+
|
29
|
+
if app_type.lower() == "web":
|
30
|
+
print("Running web application")
|
31
|
+
javacore_analyser_web.run_web(args.debug, args.port, args.reports_dir)
|
32
|
+
elif app_type.lower() == "batch":
|
33
|
+
print("Running batch application")
|
34
|
+
javacore_analyser_batch.batch_process(args.input, args.output, args.separator)
|
35
|
+
else:
|
36
|
+
print('Invalid application type. Available types: "batch" or "web"')
|
37
|
+
|
38
|
+
|
39
|
+
if __name__ == '__main__':
|
40
|
+
# This is the code to be able to run the app from command line.
|
41
|
+
# Try this:
|
42
|
+
# python -m javacore_analyser -h
|
43
|
+
main()
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
|
3
|
+
<!--
|
4
|
+
# Copyright IBM Corp. 2024 - 2025
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
6
|
+
-->
|
7
|
+
|
8
|
+
<html lang="en">
|
9
|
+
<head>
|
10
|
+
<meta charset="UTF-8">
|
11
|
+
<title>Processing failed</title>
|
12
|
+
</head>
|
13
|
+
<body>
|
14
|
+
<p>
|
15
|
+
Processing failed with an error. Check the log file. If the issue is a product defect, rais it on
|
16
|
+
<a href="https://github.com/IBM/javacore-analyser/issues/new?template=bug_report.md">Bug report</a> page.
|
17
|
+
</p>
|
18
|
+
<p>Please attach the stack trace</p>
|
19
|
+
<p>Stack trace: </p>
|
20
|
+
<code> {stacktrace} </code>
|
21
|
+
</body>
|
22
|
+
</html>
|
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
/*
|
2
|
+
Copyright IBM Corp. 2024 - 2025
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
4
|
+
*/
|
5
|
+
|
4
6
|
/* overall */
|
5
7
|
.tablesorter-blue {
|
6
8
|
width: 100%;
|
@@ -109,6 +111,10 @@
|
|
109
111
|
background-color: red
|
110
112
|
}
|
111
113
|
|
114
|
+
.tablesorter-blue td.http_failure {
|
115
|
+
background-color: red
|
116
|
+
}
|
117
|
+
|
112
118
|
/* hovered row colors
|
113
119
|
you'll need to add additional lines for
|
114
120
|
rows with more than 2 child rows
|
@@ -99,7 +99,9 @@ const loadChartGC = function() {
|
|
99
99
|
}
|
100
100
|
|
101
101
|
const sysResourceE3Elem = document.getElementById('systemresources_myChartGC');
|
102
|
-
sysResourceE3Elem
|
102
|
+
if (sysResourceE3Elem) {
|
103
|
+
sysResourceE3Elem.classList.remove('hide');
|
104
|
+
}
|
103
105
|
|
104
106
|
const ctx = document.getElementById('myChartGC');
|
105
107
|
|
@@ -125,7 +127,7 @@ const loadChartGC = function() {
|
|
125
127
|
startingPoint = timestamp;
|
126
128
|
|
127
129
|
if(endingPoint < timestamp)
|
128
|
-
endingPoint
|
130
|
+
endingPoint = timestamp;
|
129
131
|
}
|
130
132
|
|
131
133
|
coresTimeRange['startTime'] = startingPoint;
|
javacore_analyser/data/style.css
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
/*
|
2
|
+
Copyright IBM Corp. 2024 - 2025
|
3
|
+
SPDX-License-Identifier: Apache-2.0
|
4
|
+
*/
|
5
|
+
|
1
6
|
table.heading {
|
2
7
|
border: none;
|
3
8
|
width: 100%;
|
@@ -100,6 +105,28 @@ td {
|
|
100
105
|
text-align: left;
|
101
106
|
}
|
102
107
|
|
108
|
+
.info {
|
109
|
+
position: relative;
|
110
|
+
display: inline-block;
|
111
|
+
border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
|
112
|
+
color: orange
|
113
|
+
}
|
114
|
+
|
115
|
+
/* Tooltip text */
|
116
|
+
.info .infotooltip {
|
117
|
+
visibility: hidden;
|
118
|
+
width: 120px;
|
119
|
+
background-color: black;
|
120
|
+
color: #fff;
|
121
|
+
text-align: center;
|
122
|
+
padding: 5px 0;
|
123
|
+
border-radius: 6px;
|
124
|
+
|
125
|
+
/* Position the tooltip text - see examples below! */
|
126
|
+
position: absolute;
|
127
|
+
z-index: 1;
|
128
|
+
}
|
129
|
+
|
103
130
|
.warning {
|
104
131
|
position: relative;
|
105
132
|
display: inline-block;
|
@@ -142,6 +169,11 @@ mark.current {
|
|
142
169
|
background: orange;
|
143
170
|
}
|
144
171
|
|
172
|
+
/* Show the tooltip text when you mouse over the tooltip container */
|
173
|
+
.info:hover .infotooltip {
|
174
|
+
visibility: visible;
|
175
|
+
}
|
176
|
+
|
145
177
|
/* Show the tooltip text when you mouse over the tooltip container */
|
146
178
|
.warning:hover .warningtooltip {
|
147
179
|
visibility: visible;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
|
3
3
|
<!--
|
4
|
-
# Copyright IBM Corp. 2024 -
|
4
|
+
# Copyright IBM Corp. 2024 - 2025
|
5
5
|
# SPDX-License-Identifier: Apache-2.0
|
6
6
|
-->
|
7
7
|
|
@@ -59,6 +59,15 @@
|
|
59
59
|
},
|
60
60
|
});
|
61
61
|
|
62
|
+
$('#har_files_table').tablesorter({
|
63
|
+
theme : 'blue',
|
64
|
+
headers: {
|
65
|
+
0: { sorter: false },
|
66
|
+
1: { sorter: false },
|
67
|
+
2: { sorter: false }
|
68
|
+
},
|
69
|
+
});
|
70
|
+
|
62
71
|
$('#java_arguments_table').tablesorter({
|
63
72
|
theme : 'blue',
|
64
73
|
widgets : ['zebra', 'columns'],
|
@@ -122,6 +131,21 @@
|
|
122
131
|
sortReset : true,
|
123
132
|
sortRestart : true
|
124
133
|
});
|
134
|
+
|
135
|
+
$('#HttpCallTable').tablesorter({
|
136
|
+
theme : 'blue',
|
137
|
+
widgets : ['zebra', 'columns'],
|
138
|
+
sortList: [
|
139
|
+
[2, 1]
|
140
|
+
],
|
141
|
+
sortInitialOrder: 'asc',
|
142
|
+
headers : {
|
143
|
+
0 : { sortInitialOrder: 'asc' }
|
144
|
+
},
|
145
|
+
usNumberFormat : false,
|
146
|
+
sortReset : true,
|
147
|
+
sortRestart : true
|
148
|
+
});
|
125
149
|
});
|
126
150
|
</script>
|
127
151
|
</head>
|
@@ -262,6 +286,49 @@
|
|
262
286
|
</xsl:when>
|
263
287
|
<xsl:otherwise> No verbose GC files </xsl:otherwise>
|
264
288
|
</xsl:choose>
|
289
|
+
<xsl:choose>
|
290
|
+
<xsl:when test="doc/har_files">
|
291
|
+
<h4>HAR files</h4>
|
292
|
+
<a id="togglehardoc" href="javascript:expand_it(hardoc,togglehardoc)" class="expandit">
|
293
|
+
What does this table tell me?</a>
|
294
|
+
<div id="hardoc" style="display:none;">
|
295
|
+
This table shows all the HAR files that are included in the data set.
|
296
|
+
<ul>
|
297
|
+
<li>
|
298
|
+
<strong>File Name</strong>
|
299
|
+
is the name of the HAR file.
|
300
|
+
</li>
|
301
|
+
<li>
|
302
|
+
<strong>Hostname</strong>
|
303
|
+
is the name of the server machine for which the HAR file was collected.
|
304
|
+
</li>
|
305
|
+
<li>
|
306
|
+
<strong>Browser</strong>
|
307
|
+
contains information about the browser that was used to collect the HAR file.
|
308
|
+
</li>
|
309
|
+
</ul>
|
310
|
+
</div>
|
311
|
+
<table id="har_files_table">
|
312
|
+
<thead>
|
313
|
+
<tr>
|
314
|
+
<th class="sixty">File Name</th>
|
315
|
+
<th class="ten">Hostname</th>
|
316
|
+
<th class="ten">Browser</th>
|
317
|
+
</tr>
|
318
|
+
</thead>
|
319
|
+
<tbody>
|
320
|
+
<xsl:for-each select="doc/har_files/har_file">
|
321
|
+
<tr>
|
322
|
+
<td class="left"><xsl:value-of select="@filename"/></td>
|
323
|
+
<td class="left"><xsl:value-of select="@hostname"/></td>
|
324
|
+
<td class="left"><xsl:value-of select="@browser"/></td>
|
325
|
+
</tr>
|
326
|
+
</xsl:for-each>
|
327
|
+
</tbody>
|
328
|
+
</table>
|
329
|
+
</xsl:when>
|
330
|
+
<!-- xsl:otherwise> No HAR files </xsl:otherwise -->
|
331
|
+
</xsl:choose>
|
265
332
|
</div>
|
266
333
|
<h3><a id="toggle_system_properties"
|
267
334
|
href="javascript:expand_it(system_properties, toggle_system_properties)"
|
@@ -355,25 +422,41 @@
|
|
355
422
|
<h4>Garbage Collection Activity</h4>
|
356
423
|
<a id="togglememusagedoc" href="javascript:expand_it(memusagedoc,togglememusagedoc)" class="expandit">
|
357
424
|
What does this chart tell me?</a>
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
425
|
+
<xsl:choose>
|
426
|
+
<xsl:when test="doc/report_info/verbose_gc_list/verbose_gc">
|
427
|
+
<xsl:choose>
|
428
|
+
<xsl:when test="//verbose_gc_list/@total_collects_in_time_limits = 0">
|
429
|
+
<br/>
|
430
|
+
There were no garbage collections withing the javacore time limits
|
431
|
+
</xsl:when>
|
432
|
+
<xsl:otherwise>
|
433
|
+
<div id="memusagedoc" style="display:none;">
|
434
|
+
This chart shows all the garbage collections that happened between the time
|
435
|
+
of the first and the last javacore in the data set.
|
436
|
+
Garbage collections that happened before the first
|
437
|
+
or after the last javacore generation time are not included.
|
438
|
+
<ul>
|
439
|
+
<li><strong>Heap Usage</strong>
|
440
|
+
is the available Java heap memory over time,
|
441
|
+
based on the garbage collection data from the verbose GC log files.
|
442
|
+
</li>
|
443
|
+
<li><strong>Total Heap</strong>
|
444
|
+
is the maximum size of the Java heap, configured by using the Xmx Java argument,
|
445
|
+
expressed in megabytes.
|
446
|
+
</li>
|
447
|
+
</ul>
|
448
|
+
</div>
|
449
|
+
<div id="systemresources_myChartGC" class="chart-container hide">
|
450
|
+
<canvas id="myChartGC" height="200"></canvas>
|
451
|
+
</div>
|
452
|
+
</xsl:otherwise>
|
453
|
+
</xsl:choose>
|
454
|
+
</xsl:when>
|
455
|
+
<xsl:otherwise>
|
456
|
+
<br/>
|
457
|
+
No verbosegc logs were provided
|
458
|
+
</xsl:otherwise>
|
459
|
+
</xsl:choose>
|
377
460
|
<h4>CPU Load</h4>
|
378
461
|
<a id="togglecpuloaddoc" href="javascript:expand_it(cpuloaddoc,togglecpuloaddoc)" class="expandit">
|
379
462
|
What does this chart tell me?</a>
|
@@ -746,6 +829,70 @@
|
|
746
829
|
</table>
|
747
830
|
</div>
|
748
831
|
|
832
|
+
<xsl:choose>
|
833
|
+
<xsl:when test="doc/har_files">
|
834
|
+
<h3><a id="toggle_http_calls" href="javascript:expand_it(http_calls,toggle_http_calls)" class="expandit">HTTP calls</a></h3>
|
835
|
+
<div id="http_calls" style="display:none;" >
|
836
|
+
<a id="togglehttpcallsdoc" href="javascript:expand_it(httpcallsdoc,togglehttpcallsdoc)" class="expandit">
|
837
|
+
What does this table tell me?</a>
|
838
|
+
<div id="httpcallsdoc" style="display:none;">
|
839
|
+
The table shows the HTTP calls that are included in the HAR files from the data set.
|
840
|
+
The table can be sorted by clicking on a column header.
|
841
|
+
<ul>
|
842
|
+
<li><strong>URL</strong>
|
843
|
+
is the URL of the HTTP request.
|
844
|
+
</li>
|
845
|
+
<li><strong>Status</strong>
|
846
|
+
is the HTTP response code.
|
847
|
+
</li>
|
848
|
+
<li><strong>Start time</strong>
|
849
|
+
is the time when the HTTP request was made.
|
850
|
+
</li>
|
851
|
+
<li><strong>Duration</strong>
|
852
|
+
is the amount of time it took to complete the HTTP call, in milliseconds.
|
853
|
+
</li>
|
854
|
+
<li><strong>Size</strong>
|
855
|
+
is size of the response body, in bytes.
|
856
|
+
</li>
|
857
|
+
</ul>
|
858
|
+
</div>
|
859
|
+
<table id="HttpCallTable" class="tablesorter">
|
860
|
+
<thead>
|
861
|
+
<tr>
|
862
|
+
<th class="sixty">URL</th>
|
863
|
+
<th>Status</th>
|
864
|
+
<th>Start Time</th>
|
865
|
+
<th>Duration</th>
|
866
|
+
<th>Size</th>
|
867
|
+
</tr>
|
868
|
+
</thead>
|
869
|
+
<tbody>
|
870
|
+
<xsl:for-each select="//http_call">
|
871
|
+
<tr>
|
872
|
+
<td class="left"><xsl:value-of select="@url"/></td>
|
873
|
+
<td>
|
874
|
+
<xsl:choose>
|
875
|
+
<xsl:when test="@success='False'">
|
876
|
+
<xsl:attribute name="class">http_failure</xsl:attribute>
|
877
|
+
</xsl:when>
|
878
|
+
</xsl:choose>
|
879
|
+
<xsl:value-of select="@status"/>
|
880
|
+
</td>
|
881
|
+
<td><xsl:value-of select="@start_time"/></td>
|
882
|
+
<td>
|
883
|
+
<div class="info"><xsl:value-of select="@duration"/>
|
884
|
+
<span class="infotooltip"><xsl:value-of select="@timings"/></span>
|
885
|
+
</div>
|
886
|
+
</td>
|
887
|
+
<td><xsl:value-of select="@size"/></td>
|
888
|
+
</tr>
|
889
|
+
</xsl:for-each>
|
890
|
+
</tbody>
|
891
|
+
</table>
|
892
|
+
</div>
|
893
|
+
</xsl:when>
|
894
|
+
</xsl:choose>
|
895
|
+
|
749
896
|
<p></p>
|
750
897
|
<div class="margined">
|
751
898
|
<a href="https://github.com/IBM/javacore-analyser/wiki" target="_blank">Documentation</a>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#
|
2
|
+
# Copyright IBM Corp. 2024 - 2025
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
4
|
+
#
|
5
|
+
import os
|
6
|
+
|
7
|
+
from haralyzer import HarParser
|
8
|
+
import json
|
9
|
+
|
10
|
+
|
11
|
+
class HarFile:
|
12
|
+
|
13
|
+
def __init__(self, path):
|
14
|
+
self.path = path
|
15
|
+
with open(path, 'r') as f:
|
16
|
+
self.har = HarParser(json.loads(f.read()))
|
17
|
+
|
18
|
+
def get_xml(self, doc):
|
19
|
+
har_file_node = doc.createElement("har_file")
|
20
|
+
har_file_node.setAttribute("filename", os.path.basename(self.path))
|
21
|
+
har_file_node.setAttribute("hostname", str(self.har.hostname))
|
22
|
+
har_file_node.setAttribute("browser", str(self.har.browser))
|
23
|
+
for page in self.har.pages:
|
24
|
+
for entry in page.entries:
|
25
|
+
http_call = HttpCall(entry)
|
26
|
+
har_file_node.appendChild(http_call.get_xml(doc))
|
27
|
+
return har_file_node
|
28
|
+
|
29
|
+
|
30
|
+
class HttpCall:
|
31
|
+
|
32
|
+
def __init__(self, call):
|
33
|
+
self.call = call
|
34
|
+
self.url = call.url
|
35
|
+
self.status = str(call.status)
|
36
|
+
self.start_time = str(call.startTime)
|
37
|
+
self.duration = str(self.get_total_time())
|
38
|
+
self.timings = str(call.timings)
|
39
|
+
self.size = str(call.response.bodySize)
|
40
|
+
self.success = str(self.get_success())
|
41
|
+
|
42
|
+
def get_total_time(self):
|
43
|
+
total = 0
|
44
|
+
if len(self.call.timings) > 0:
|
45
|
+
for key in self.call.timings.keys():
|
46
|
+
time = int(self.call.timings[key])
|
47
|
+
if time > 0:
|
48
|
+
total += time
|
49
|
+
return total
|
50
|
+
|
51
|
+
def get_success(self):
|
52
|
+
if self.status.startswith('4') or self.status.startswith('5'):
|
53
|
+
return False
|
54
|
+
return True
|
55
|
+
|
56
|
+
def get_xml(self, doc):
|
57
|
+
http_call_node = doc.createElement("http_call")
|
58
|
+
http_call_node.setAttribute("url", self.url)
|
59
|
+
http_call_node.setAttribute("status", self.status)
|
60
|
+
http_call_node.setAttribute("start_time", self.start_time)
|
61
|
+
http_call_node.setAttribute("duration", self.duration)
|
62
|
+
http_call_node.setAttribute("timings", self.timings)
|
63
|
+
http_call_node.setAttribute("size", self.size)
|
64
|
+
http_call_node.setAttribute("success", self.success)
|
65
|
+
return http_call_node
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright IBM Corp. 2024 -
|
2
|
+
# Copyright IBM Corp. 2024 - 2025
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
#
|
5
5
|
|
@@ -12,6 +12,7 @@ import shutil
|
|
12
12
|
import sys
|
13
13
|
import tarfile
|
14
14
|
import tempfile
|
15
|
+
import traceback
|
15
16
|
import zipfile
|
16
17
|
|
17
18
|
import importlib_resources
|
@@ -64,11 +65,6 @@ def extract_archive(input_archive_filename, output_path):
|
|
64
65
|
|
65
66
|
|
66
67
|
def main():
|
67
|
-
logging_utils.create_console_logging()
|
68
|
-
logging.info("IBM Javacore analyser")
|
69
|
-
logging.info("Python version: " + sys.version)
|
70
|
-
logging.info("Preferred encoding: " + locale.getpreferredencoding())
|
71
|
-
|
72
68
|
parser = argparse.ArgumentParser()
|
73
69
|
parser.add_argument("input", help="Input javacore file(s) or directory with javacores. "
|
74
70
|
"The javacores can be packed "
|
@@ -86,12 +82,19 @@ def main():
|
|
86
82
|
output_param = args.output
|
87
83
|
files_separator = args.separator
|
88
84
|
|
85
|
+
batch_process(input_param, output_param, files_separator)
|
86
|
+
|
87
|
+
|
88
|
+
def batch_process(input_param, output_param, files_separator=DEFAULT_FILE_DELIMITER):
|
89
|
+
logging_utils.create_console_logging()
|
90
|
+
logging.info("IBM Javacore analyser")
|
91
|
+
logging.info("Python version: " + sys.version)
|
92
|
+
logging.info("Preferred encoding: " + locale.getpreferredencoding())
|
89
93
|
logging.info("Input parameter: " + input_param)
|
90
94
|
logging.info("Report directory: " + output_param)
|
91
|
-
|
95
|
+
output_param = os.path.normpath(output_param)
|
92
96
|
# Needs to be created once output file structure is ready.
|
93
97
|
logging_utils.create_file_logging(output_param)
|
94
|
-
|
95
98
|
# Check whether as input we got list of files or single file
|
96
99
|
# Semicolon is separation mark for list of input files
|
97
100
|
if files_separator in input_param or fnmatch.fnmatch(input_param, '*javacore*.txt'):
|
@@ -100,6 +103,7 @@ def main():
|
|
100
103
|
else:
|
101
104
|
files = [input_param]
|
102
105
|
try:
|
106
|
+
files = [os.path.normpath(file) for file in files]
|
103
107
|
process_javacores_and_generate_report_data(files, output_param)
|
104
108
|
except Exception as ex:
|
105
109
|
logging.exception(ex)
|
@@ -156,6 +160,15 @@ def create_output_files_structure(output_dir):
|
|
156
160
|
os.path.join(output_dir, "index.html"))
|
157
161
|
|
158
162
|
|
163
|
+
def generate_error_page(output_dir, exception):
|
164
|
+
error_page_text = importlib_resources.read_text("javacore_analyser", "data/html/error.html")
|
165
|
+
tb = traceback.format_exc()
|
166
|
+
file = os.path.join(output_dir, "index.html")
|
167
|
+
f = open(file, "w")
|
168
|
+
f.write(error_page_text.format(stacktrace=tb))
|
169
|
+
f.close()
|
170
|
+
|
171
|
+
|
159
172
|
# Assisted by WCA@IBM
|
160
173
|
# Latest GenAI contribution: ibm/granite-8b-code-instruct
|
161
174
|
def process_javacores_and_generate_report_data(input_files, output_dir):
|
@@ -169,9 +182,14 @@ def process_javacores_and_generate_report_data(input_files, output_dir):
|
|
169
182
|
Returns:
|
170
183
|
None
|
171
184
|
"""
|
172
|
-
|
173
|
-
|
174
|
-
|
185
|
+
try:
|
186
|
+
create_output_files_structure(output_dir)
|
187
|
+
javacore_set = generate_javecore_set_data(input_files)
|
188
|
+
javacore_set.generate_report_files(output_dir)
|
189
|
+
except Exception as ex:
|
190
|
+
logging.exception(ex)
|
191
|
+
logging.error("Processing was not successful. Correct the problem and try again.")
|
192
|
+
generate_error_page(output_dir, ex)
|
175
193
|
|
176
194
|
|
177
195
|
if __name__ == "__main__":
|
@@ -132,9 +132,14 @@ def main():
|
|
132
132
|
args = parser.parse_args()
|
133
133
|
debug = args.debug
|
134
134
|
port = args.port
|
135
|
-
|
136
|
-
|
135
|
+
reports_directory = args.reports_dir
|
136
|
+
|
137
|
+
run_web(debug, port, reports_directory)
|
138
|
+
|
137
139
|
|
140
|
+
def run_web(debug=False, port=5000, reports_directory=DEFAULT_REPORTS_DIR):
|
141
|
+
global reports_dir
|
142
|
+
reports_dir = reports_directory
|
138
143
|
create_console_logging()
|
139
144
|
logging.info("Javacore analyser")
|
140
145
|
logging.info("Python version: " + sys.version)
|
@@ -142,7 +147,6 @@ def main():
|
|
142
147
|
logging.info("Reports directory: " + reports_dir)
|
143
148
|
create_file_logging(reports_dir)
|
144
149
|
create_temp_data_in_reports_dir(reports_dir)
|
145
|
-
|
146
150
|
if debug:
|
147
151
|
app.run(debug=True, port=port) # Run Flask for development
|
148
152
|
else:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright IBM Corp. 2024 -
|
2
|
+
# Copyright IBM Corp. 2024 - 2025
|
3
3
|
# SPDX-License-Identifier: Apache-2.0
|
4
4
|
#
|
5
5
|
|
@@ -22,6 +22,7 @@ from tqdm import tqdm
|
|
22
22
|
from javacore_analyser import tips
|
23
23
|
from javacore_analyser.code_snapshot_collection import CodeSnapshotCollection
|
24
24
|
from javacore_analyser.constants import *
|
25
|
+
from javacore_analyser.har_file import HarFile
|
25
26
|
from javacore_analyser.java_thread import Thread
|
26
27
|
from javacore_analyser.javacore import Javacore
|
27
28
|
from javacore_analyser.snapshot_collection import SnapshotCollection
|
@@ -87,6 +88,7 @@ class JavacoreSet:
|
|
87
88
|
self.blocked_snapshots = []
|
88
89
|
self.tips = []
|
89
90
|
self.gc_parser = VerboseGcParser()
|
91
|
+
self.har_files = []
|
90
92
|
|
91
93
|
# Assisted by WCA@IBM
|
92
94
|
# Latest GenAI contribution: ibm/granite-8b-code-instruct
|
@@ -140,16 +142,18 @@ class JavacoreSet:
|
|
140
142
|
|
141
143
|
@staticmethod
|
142
144
|
def __generate_placeholder_htmls(placeholder_file, directory, collection, file_prefix):
|
145
|
+
logging.info("Generating placeholder htmls")
|
143
146
|
if os.path.exists(directory):
|
144
147
|
shutil.rmtree(directory)
|
145
148
|
os.mkdir(directory)
|
146
149
|
|
147
|
-
for element in tqdm(collection, desc="Generating placeholder htmls", unit="
|
150
|
+
for element in tqdm(collection, desc="Generating placeholder htmls", unit=" files"):
|
148
151
|
filename = file_prefix + "_" + element.get_id() + ".html"
|
149
152
|
if filename.startswith("_"):
|
150
153
|
filename = filename[1:]
|
151
154
|
file_path = os.path.join(directory, filename)
|
152
155
|
shutil.copy2(placeholder_file, file_path)
|
156
|
+
logging.info("Finished generating placeholder htmls")
|
153
157
|
|
154
158
|
def __generate_htmls_for_threads(self, output_dir, temp_dir_name):
|
155
159
|
_create_xml_xsl_for_collection(os.path.join(temp_dir_name, "threads"),
|
@@ -230,6 +234,9 @@ class JavacoreSet:
|
|
230
234
|
if fnmatch.fnmatch(file, '*verbosegc*.txt*'):
|
231
235
|
self.gc_parser.add_file(dirpath + os.sep + file)
|
232
236
|
logging.info("VerboseGC file found: " + file)
|
237
|
+
if fnmatch.fnmatch(file, "*.har"):
|
238
|
+
self.har_files.append(HarFile(dirpath + os.sep + file))
|
239
|
+
logging.info("HAR file found: " + file)
|
233
240
|
|
234
241
|
# sorting files by name.
|
235
242
|
# Unless the user changed the javacore file name format, this is equivalent to sorting by date
|
@@ -385,6 +392,8 @@ class JavacoreSet:
|
|
385
392
|
|
386
393
|
verbose_gc_list_node = self.doc.createElement("verbose_gc_list")
|
387
394
|
report_info_node.appendChild(verbose_gc_list_node)
|
395
|
+
|
396
|
+
total_collects_in_time_limits = 0
|
388
397
|
for vgc in self.gc_parser.get_files():
|
389
398
|
verbose_gc_node = self.doc.createElement("verbose_gc")
|
390
399
|
verbose_gc_list_node.appendChild(verbose_gc_node)
|
@@ -394,9 +403,17 @@ class JavacoreSet:
|
|
394
403
|
verbose_gc_collects_node = self.doc.createElement("verbose_gc_collects")
|
395
404
|
verbose_gc_node.appendChild(verbose_gc_collects_node)
|
396
405
|
verbose_gc_collects_node.appendChild(self.doc.createTextNode(str(vgc.get_number_of_collects())))
|
406
|
+
total_collects_in_time_limits += vgc.get_number_of_collects()
|
397
407
|
verbose_gc_total_collects_node = self.doc.createElement("verbose_gc_total_collects")
|
398
408
|
verbose_gc_node.appendChild(verbose_gc_total_collects_node)
|
399
409
|
verbose_gc_total_collects_node.appendChild(self.doc.createTextNode(str(vgc.get_total_number_of_collects())))
|
410
|
+
verbose_gc_list_node.setAttribute("total_collects_in_time_limits", str(total_collects_in_time_limits))
|
411
|
+
|
412
|
+
if len(self.har_files) > 0:
|
413
|
+
har_files_node = self.doc.createElement("har_files")
|
414
|
+
doc_node.appendChild(har_files_node)
|
415
|
+
for har in self.har_files:
|
416
|
+
har_files_node.appendChild(har.get_xml(self.doc))
|
400
417
|
|
401
418
|
system_info_node = self.doc.createElement("system_info")
|
402
419
|
doc_node.appendChild(system_info_node)
|
javacore_analyser/verbose_gc.py
CHANGED
@@ -155,7 +155,6 @@ class VerboseGcFile:
|
|
155
155
|
gets the total number of gc collections in this VerboseGcFile
|
156
156
|
regardless of the time when tey occurred with regards to the javacores
|
157
157
|
'''
|
158
|
-
|
159
158
|
def get_total_number_of_collects(self):
|
160
159
|
if self.__total_number_of_collects < 0:
|
161
160
|
self.get_collects()
|
@@ -1,10 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: javacore_analyser
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.2rc1
|
4
4
|
Summary: The tool to review IBM Javacore files
|
5
5
|
Project-URL: Homepage, https://github.com/IBM/javacore-analyser
|
6
6
|
Project-URL: Issues, https://github.com/IBM/javacore-analyser/issues
|
7
|
-
Project-URL: Changelog, https://github.com/IBM/javacore-analyser/CHANGELOG.md
|
7
|
+
Project-URL: Changelog, https://github.com/IBM/javacore-analyser/blob/main/CHANGELOG.md
|
8
8
|
Project-URL: Source, https://github.com/IBM/javacore-analyser
|
9
9
|
Author-email: Krzysztof Kazmierczyk <kazm@ibm.com>, Piotr Aniola <Piotr.Aniola@ibm.com>, Tadeusz Janasiewicz <t.janasiewicz@ibm.com>
|
10
10
|
License: Apache License
|
@@ -228,6 +228,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
228
228
|
Classifier: Programming Language :: Python :: 3.13
|
229
229
|
Requires-Python: >=3.9
|
230
230
|
Requires-Dist: flask
|
231
|
+
Requires-Dist: haralyzer
|
231
232
|
Requires-Dist: importlib-resources
|
232
233
|
Requires-Dist: lxml
|
233
234
|
Requires-Dist: py7zr
|
@@ -239,8 +240,18 @@ Description-Content-Type: text/markdown
|
|
239
240
|
<!-- This should be the location of the title of the repository, normally the short name -->
|
240
241
|
# Javacore Analyser
|
241
242
|
|
243
|
+

|
244
|
+

|
245
|
+

|
242
246
|
<!-- Build Status, is a great thing to have at the top of your repository, it shows that you take your CI/CD as first class citizens -->
|
243
247
|
[](https://app.travis-ci.com/IBM/javacore-analyser)
|
248
|
+

|
249
|
+

|
250
|
+

|
251
|
+

|
252
|
+

|
253
|
+

|
254
|
+
|
244
255
|
|
245
256
|
<!-- Not always needed, but a scope helps the user understand in a short sentance like below, why this repo exists -->
|
246
257
|
## Scope
|
@@ -267,7 +278,7 @@ Steps:
|
|
267
278
|
3. Run the following command:
|
268
279
|
`pip install javacore-analyser`
|
269
280
|
OR
|
270
|
-
`pip install --extra-index-url https://test.pypi.org/simple/ javacore-analyser` - if you want an experimental version
|
281
|
+
`pip install --pre --extra-index-url https://test.pypi.org/simple/ javacore-analyser` - if you want an experimental version
|
271
282
|
|
272
283
|
#### Installing from sources
|
273
284
|
This is recommended for geeks only:
|
@@ -281,23 +292,29 @@ This is recommended for geeks only:
|
|
281
292
|
#### Running cmd application:
|
282
293
|
1. Install application if not done yet
|
283
294
|
2. Activate your created virtual environment according to activate Virtual Environment according to [Creating virtual environments](https://docs.python.org/3/tutorial/venv.html#creating-virtual-environments)
|
284
|
-
3. Run the following command from cmd:
|
295
|
+
3. Run the following command from cmd:
|
296
|
+
`javacore-analyser-batch <input-data> <generated-reports-dir>`
|
297
|
+
or
|
298
|
+
`python -m javacore_analyser batch <input-data> <generated-reports-dir>`
|
299
|
+
|
285
300
|
Where `<input-data>` is one of the following:
|
286
301
|
* The directory containing javacores and optionally verbose gc
|
287
302
|
* Archive (7z, zip, tar.gz, tar.bz2) containing the same
|
288
303
|
* List of the javacores separated by `;` character. Optionally you can add `--separator` option to define your own separator.
|
289
304
|
You can type the following command to obtain the help:
|
290
|
-
`javacore-analyser-batch --help`
|
305
|
+
`javacore-analyser-batch --help` or `python -m javacore_analyser batch --help`
|
291
306
|
|
292
307
|
#### Running web application:
|
293
308
|
1. Repeat steps 1-3 from cmd application
|
294
309
|
2. Execute the following command from cmd:
|
295
|
-
`javacore_analyser_web --port=
|
310
|
+
`javacore_analyser_web --port=5000 --reports-dir=/data/reports_dir`
|
311
|
+
or
|
312
|
+
`python -m javacore_analyser web --port=5000 --reports-dir=/data/reports_dir`
|
296
313
|
|
297
|
-
|
298
|
-
|
314
|
+
The first parameter set the port to use by application. If not specified, 5000 will be used.
|
315
|
+
The second parameter sets where the reports need to be stored. If not set, then the `reports` dir will be created in current location.
|
299
316
|
|
300
|
-
|
317
|
+
Now you can type (http://localhost:5000/).
|
301
318
|
|
302
319
|
### Running container image
|
303
320
|
There is an unofficial Docker/Podman container managed by one of projects developers. Use the following command
|
@@ -1,12 +1,14 @@
|
|
1
1
|
javacore_analyser/__init__.py,sha256=Sw2ZeqcI2Kx1cDDv083n1SiSY_FDRCmidTuzaN1uRSw,76
|
2
|
+
javacore_analyser/__main__.py,sha256=wQCPgu8Gp7XczyNckNGmY30c5YMUMRByW7jrdFO0OBY,1694
|
2
3
|
javacore_analyser/abstract_snapshot_collection.py,sha256=jGfd2XgujurRlKgEtlJjqNJK9sUvTdFsdgFnX9oLzt4,5589
|
3
4
|
javacore_analyser/code_snapshot_collection.py,sha256=6_C5myag5ocjOTwXVDbBamN6Lf1szgS3ylSHEEjUdVg,2655
|
4
5
|
javacore_analyser/constants.py,sha256=iGYAznPK8AySq6uqk-cpCU8Dbjbq6PrCh6q2mF8oeu8,1003
|
6
|
+
javacore_analyser/har_file.py,sha256=grXpfIyPek9xQ5jp3_AYOB5JDELd17o4O4rYELxWO7w,2131
|
5
7
|
javacore_analyser/java_thread.py,sha256=4zUfmmlH47SrIxgfPmrJHl_YUziVJXVNVedD5X25vXY,4464
|
6
8
|
javacore_analyser/javacore.py,sha256=_2abTyvXEaZ6Tx8r9d3NEzRCIBcf4Is8lSjpKyPu-R8,6884
|
7
|
-
javacore_analyser/javacore_analyser_batch.py,sha256=
|
8
|
-
javacore_analyser/javacore_analyser_web.py,sha256=
|
9
|
-
javacore_analyser/javacore_set.py,sha256=
|
9
|
+
javacore_analyser/javacore_analyser_batch.py,sha256=D9H6ct_PBAXR_PvTqGtKw_FIx9Q9KuJSFBeEZ2FIkbo,7607
|
10
|
+
javacore_analyser/javacore_analyser_web.py,sha256=o-Spq119Wi7w4pvBa7M7ZrxiZnzKmWqDhCdGtEReQAU,5951
|
11
|
+
javacore_analyser/javacore_set.py,sha256=R3QiyDfDOBtzTUwQzS8ft2-Ca7fkReSD5KJzgZl6oVY,32103
|
10
12
|
javacore_analyser/logging_utils.py,sha256=vLob0ikezysjGv9XGqv9GbLekxu4eO_csq22M-gtLiQ,966
|
11
13
|
javacore_analyser/snapshot_collection.py,sha256=fLEnwg9-cOjVVUUludtzI7R2yO9BBVgJgxkhvqG5QDg,443
|
12
14
|
javacore_analyser/snapshot_collection_collection.py,sha256=1PV1TX4QQk01dAbX-k-kTpgKr6Il867Bw6X7HHBuv-Q,1346
|
@@ -15,9 +17,10 @@ javacore_analyser/stack_trace_element.py,sha256=pZPrK1ACBUDE7YsVOFhTfewXequ1m5P-
|
|
15
17
|
javacore_analyser/stack_trace_kind.py,sha256=lOdfb_F3XrwDLciPk_ZgM_fmMn5JoXsIUjr7pjvmU4M,157
|
16
18
|
javacore_analyser/thread_snapshot.py,sha256=2Do8NPBXdpUezQrUI_9nyGbtU4b2s5euPnHqcuuKq7U,13255
|
17
19
|
javacore_analyser/tips.py,sha256=EhwLUAha0FvFJtO5kmvba9a1nKXGdqNHFa2jFbHZr4U,8655
|
18
|
-
javacore_analyser/verbose_gc.py,sha256=
|
20
|
+
javacore_analyser/verbose_gc.py,sha256=r5ZOZVhdrrgFTGo1Rx-FFPFNRpvX1jflP6AkNATMpIQ,6871
|
19
21
|
javacore_analyser/data/expand.js,sha256=KwqvNUoO7yMDeQKcnLDywfMdR3Zsjan5L8QoPsQQLGo,956
|
20
|
-
javacore_analyser/data/style.css,sha256=
|
22
|
+
javacore_analyser/data/style.css,sha256=HSKPajW3EItHjye6mSGNMRPEzfE2r7o1Gq-BEAI54Ts,2879
|
23
|
+
javacore_analyser/data/html/error.html,sha256=dJI5RdeNL1E4Y-zaU7NTBqrsxCuAovVc1Cebrk5GcYA,520
|
21
24
|
javacore_analyser/data/html/processing_data.html,sha256=S1S2GMXQ8oQdqdYTcPzVMxUib-NLtM4ffT3OJaIIO7w,421
|
22
25
|
javacore_analyser/data/jquery/chart.js,sha256=tgiW1vJqfIKxE0F2uVvsXbgUlTyrhPMY_sm30hh_Sxc,203464
|
23
26
|
javacore_analyser/data/jquery/chartjs-adapter-date-fns.bundle.min.js,sha256=6nqzDSbDjc8fLSa7Q-c6lFN7WPGQb1XhpUbdCTIbVhU,50650
|
@@ -28,18 +31,18 @@ javacore_analyser/data/jquery/jquery.tablesorter.min.js,sha256=dtGH1XcAyKopMui5x
|
|
28
31
|
javacore_analyser/data/jquery/jquery.tablesorter.widgets.min.js,sha256=GxbszpUzg-iYIcyDGyNVLz9Y0dQvzmQgXXVk5cHJbw0,53100
|
29
32
|
javacore_analyser/data/jquery/search.js,sha256=Jwi-cBJ9YKDHJwqIlcKXqrpcM1BX-wx93uKAR44JLww,4200
|
30
33
|
javacore_analyser/data/jquery/sorting.js,sha256=HsuVLa7F70IM4ZMXZpjj7wtVI1TXL1SPbZGWenv0Jp8,369
|
31
|
-
javacore_analyser/data/jquery/theme.blue.css,sha256=
|
34
|
+
javacore_analyser/data/jquery/theme.blue.css,sha256=cPcj8KaUj_zNy_xtDfrodSLue94nnYgyVNIZRusggCw,7624
|
32
35
|
javacore_analyser/data/jquery/theme.default.min.css,sha256=5sgExNTnkN8NcApKIU73_aqgZmqq_zJp9-9zXf9aSEw,4502
|
33
|
-
javacore_analyser/data/jquery/wait2scripts.js,sha256=
|
36
|
+
javacore_analyser/data/jquery/wait2scripts.js,sha256=z6zmSAak0R6bjh7BeHlIOSImiZSy5Y3z5ygMiN-sPxI,8460
|
34
37
|
javacore_analyser/data/xml/index.xml,sha256=9VH2rmri3FQpXcW39kbyi2dON94C5XTiaQn0ioExCe8,282
|
35
|
-
javacore_analyser/data/xml/report.xsl,sha256=
|
38
|
+
javacore_analyser/data/xml/report.xsl,sha256=_0b2i97QvCnauC-ZiNWndTQZzWGM18DH_hU7k4kUIno,58761
|
36
39
|
javacore_analyser/data/xml/javacores/javacore.xml,sha256=6dG89Whx1_kpEYVS_F6Upa2XuXnXorlQATFc8kD5Mfc,280
|
37
40
|
javacore_analyser/data/xml/javacores/javacore.xsl,sha256=5cnIp08Q9FccljHH8duoJQYofyW8lwUCGtpdzz5Y0Y8,11644
|
38
41
|
javacore_analyser/data/xml/threads/thread.xml,sha256=6dG89Whx1_kpEYVS_F6Upa2XuXnXorlQATFc8kD5Mfc,280
|
39
42
|
javacore_analyser/data/xml/threads/thread.xsl,sha256=rkqr5GQ2aZ_xrdhUjl2QZDCZ-09zxqUmtV8DFZVjTAA,13927
|
40
43
|
javacore_analyser/templates/index.html,sha256=aEuyry-HZ9HlQNwfbugugvqbSxwlo7LrQnrDmqO34YE,1682
|
41
|
-
javacore_analyser-2.
|
42
|
-
javacore_analyser-2.
|
43
|
-
javacore_analyser-2.
|
44
|
-
javacore_analyser-2.
|
45
|
-
javacore_analyser-2.
|
44
|
+
javacore_analyser-2.2rc1.dist-info/METADATA,sha256=k0X6Ym946yfW7F5FPJsEdKit9HJENda2Vw4F1syALSA,22285
|
45
|
+
javacore_analyser-2.2rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
46
|
+
javacore_analyser-2.2rc1.dist-info/entry_points.txt,sha256=W3S799zI58g5-jWMsC3wY9xksz21LPEMYOILv8sayfM,160
|
47
|
+
javacore_analyser-2.2rc1.dist-info/licenses/LICENSE,sha256=xllut76FgcGL5zbIRvuRc7aezPbvlMUTWJPsVr2Sugg,11358
|
48
|
+
javacore_analyser-2.2rc1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|