javacore-analyser 2.0rc1__py3-none-any.whl → 2.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- javacore_analyser/__main__.py +43 -0
- javacore_analyser/abstract_snapshot_collection.py +2 -2
- javacore_analyser/constants.py +2 -1
- javacore_analyser/data/expand.js +2 -0
- javacore_analyser/data/html/processing_data.html +17 -0
- javacore_analyser/data/jquery/search.js +22 -0
- javacore_analyser/data/jquery/wait2scripts.js +31 -7
- javacore_analyser/data/xml/javacores/javacore.xsl +126 -117
- javacore_analyser/data/xml/report.xsl +36 -20
- javacore_analyser/data/xml/threads/thread.xsl +162 -153
- javacore_analyser/javacore.py +5 -3
- javacore_analyser/javacore_analyser_batch.py +45 -22
- javacore_analyser/javacore_analyser_web.py +62 -26
- javacore_analyser/javacore_set.py +82 -43
- javacore_analyser/snapshot_collection_collection.py +5 -3
- javacore_analyser/stack_trace.py +2 -2
- javacore_analyser/stack_trace_element.py +1 -1
- javacore_analyser/templates/index.html +9 -4
- javacore_analyser/thread_snapshot.py +3 -2
- javacore_analyser/tips.py +5 -3
- javacore_analyser/verbose_gc.py +4 -2
- {javacore_analyser-2.0rc1.dist-info → javacore_analyser-2.1.dist-info}/METADATA +46 -20
- javacore_analyser-2.1.dist-info/RECORD +46 -0
- {javacore_analyser-2.0rc1.dist-info → javacore_analyser-2.1.dist-info}/WHEEL +1 -1
- javacore_analyser-2.0rc1.dist-info/RECORD +0 -44
- {javacore_analyser-2.0rc1.dist-info → javacore_analyser-2.1.dist-info}/entry_points.txt +0 -0
- {javacore_analyser-2.0rc1.dist-info → javacore_analyser-2.1.dist-info}/licenses/LICENSE +0 -0
@@ -20,177 +20,186 @@
|
|
20
20
|
<script type="text/javascript" src="../data/jquery/chart.js"> _ </script>
|
21
21
|
<script type="text/javascript" src="../data/jquery/chartjs-adapter-date-fns.bundle.min.js"> _ </script>
|
22
22
|
<script type="text/javascript" src="../data/jquery/wait2scripts.js"> _ </script>
|
23
|
-
|
23
|
+
<script src="../data/jquery/jquery.mark.min.js"> _ </script>
|
24
|
+
<script type="text/javascript" src="../data/jquery/search.js"> _ </script>
|
24
25
|
</head>
|
25
|
-
|
26
26
|
<body id="doc_body" height="100%">
|
27
|
-
<
|
28
|
-
|
29
|
-
|
30
|
-
<
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
<
|
42
|
-
<
|
43
|
-
<
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
<
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
</xsl:choose>
|
73
|
-
<xsl:choose>
|
74
|
-
<xsl:when test="position()=1">
|
75
|
-
<td>N/A</td>
|
76
|
-
</xsl:when>
|
77
|
-
<xsl:otherwise>
|
78
|
-
<td><xsl:value-of select='format-number(cpu_usage, "0.##")'/></td>
|
79
|
-
</xsl:otherwise>
|
80
|
-
</xsl:choose>
|
81
|
-
<xsl:choose>
|
27
|
+
<div class="searchbar">
|
28
|
+
<input id="search-input" type="search" />
|
29
|
+
<button data-search="search" id="search-button">Search</button>
|
30
|
+
<button data-search="next">Next</button>
|
31
|
+
<button data-search="prev">Prev</button>
|
32
|
+
<button data-search="clear">✖</button>
|
33
|
+
</div>
|
34
|
+
<div class="content">
|
35
|
+
<p class="right"><a href="../index.html"> Back to Main page </a></p>
|
36
|
+
<h2>Wait Report for thread: <b><xsl:value-of select="thread_name"/></b></h2>
|
37
|
+
<xsl:choose>
|
38
|
+
<xsl:when test="//javacore_count = 1">
|
39
|
+
System resource utilization data cannot be calculated with only a single javacore.
|
40
|
+
</xsl:when>
|
41
|
+
<xsl:otherwise>
|
42
|
+
<div class="chart-container" height="25%">
|
43
|
+
<canvas id="myChart" height="100%"></canvas>
|
44
|
+
</div>
|
45
|
+
</xsl:otherwise>
|
46
|
+
</xsl:choose>
|
47
|
+
<div id="all_threads">
|
48
|
+
<table id="all_threads_table_thread_xsl">
|
49
|
+
<thead>
|
50
|
+
<tr>
|
51
|
+
<th>Timestamp</th>
|
52
|
+
<th>Elapsed time (s)</th>
|
53
|
+
<th>CPU usage (s)</th>
|
54
|
+
<th>% CPU usage</th>
|
55
|
+
<th class='sixty'>Stack trace</th>
|
56
|
+
<th>State</th>
|
57
|
+
<th>Blocking</th>
|
58
|
+
</tr>
|
59
|
+
</thead>
|
60
|
+
<!-- Snapshot starts here -->
|
61
|
+
<xsl:for-each select="*[starts-with(name(), 'stack')]">
|
62
|
+
<tr>
|
63
|
+
<td>
|
64
|
+
<a>
|
65
|
+
<xsl:attribute name="href">
|
66
|
+
../javacores/<xsl:value-of select="file_name"/>.html
|
67
|
+
</xsl:attribute>
|
68
|
+
<xsl:value-of select='timestamp'/>
|
69
|
+
</a>
|
70
|
+
</td>
|
71
|
+
<xsl:choose>
|
82
72
|
<xsl:when test="position()=1">
|
83
73
|
<td>N/A</td>
|
84
74
|
</xsl:when>
|
85
75
|
<xsl:otherwise>
|
86
|
-
<td
|
76
|
+
<td>
|
77
|
+
<xsl:value-of select='format-number(elapsed_time, "0.##")'/>
|
78
|
+
</td>
|
87
79
|
</xsl:otherwise>
|
88
80
|
</xsl:choose>
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
<xsl:value-of select="current()"/>
|
101
|
-
</span>
|
102
|
-
<br/>
|
103
|
-
</xsl:for-each>
|
104
|
-
</p>
|
81
|
+
<xsl:choose>
|
82
|
+
<xsl:when test="position()=1">
|
83
|
+
<td>N/A</td>
|
84
|
+
</xsl:when>
|
85
|
+
<xsl:otherwise>
|
86
|
+
<td><xsl:value-of select='format-number(cpu_usage, "0.##")'/></td>
|
87
|
+
</xsl:otherwise>
|
88
|
+
</xsl:choose>
|
89
|
+
<xsl:choose>
|
90
|
+
<xsl:when test="position()=1">
|
91
|
+
<td>N/A</td>
|
105
92
|
</xsl:when>
|
106
93
|
<xsl:otherwise>
|
107
|
-
|
94
|
+
<td><xsl:value-of select='format-number(cpu_percentage, "0.#")'/></td>
|
108
95
|
</xsl:otherwise>
|
109
96
|
</xsl:choose>
|
110
|
-
|
111
|
-
|
112
|
-
<xsl:choose>
|
113
|
-
<xsl:when test="state='CW'">
|
114
|
-
<td class="waiting">
|
115
|
-
<xsl:choose>
|
116
|
-
<xsl:when test="blocked_by=''">
|
117
|
-
Waiting on condition
|
118
|
-
</xsl:when>
|
119
|
-
<xsl:otherwise>
|
120
|
-
<a target="_blank">
|
121
|
-
<xsl:attribute name="href">
|
122
|
-
<xsl:value-of select="concat('thread_', blocked_by/@thread_hash, '.html')"/>
|
123
|
-
</xsl:attribute>
|
124
|
-
<xsl:attribute name="title">
|
125
|
-
<xsl:value-of select="blocked_by/@name" />
|
126
|
-
</xsl:attribute>
|
127
|
-
Waiting for <xsl:value-of select="blocked_by/@thread_id"/>
|
128
|
-
</a>
|
129
|
-
</xsl:otherwise>
|
130
|
-
</xsl:choose>
|
131
|
-
</td>
|
132
|
-
</xsl:when>
|
133
|
-
<xsl:when test="state='R'">
|
134
|
-
<td class="runnable">Runnable</td>
|
135
|
-
</xsl:when>
|
136
|
-
<xsl:when test="state='P'">
|
137
|
-
<td class="parked">
|
97
|
+
<td class="left">
|
98
|
+
<div>
|
138
99
|
<xsl:choose>
|
139
|
-
<xsl:when test="
|
140
|
-
|
100
|
+
<xsl:when test="stack_depth > 0">
|
101
|
+
<div class="toggle_expand">
|
102
|
+
<a href="javaScript:;" class="show">[+] Expand</a>
|
103
|
+
</div>
|
104
|
+
<p class="stacktrace">
|
105
|
+
<xsl:for-each select="*[starts-with(name(), 'line')]">
|
106
|
+
<span>
|
107
|
+
<xsl:attribute name="class"><xsl:value-of select="@kind"/></xsl:attribute>
|
108
|
+
<xsl:value-of select="current()"/>
|
109
|
+
</span>
|
110
|
+
<br/>
|
111
|
+
</xsl:for-each>
|
112
|
+
</p>
|
141
113
|
</xsl:when>
|
142
114
|
<xsl:otherwise>
|
143
|
-
|
144
|
-
<xsl:attribute name="href">
|
145
|
-
<xsl:value-of select="concat('thread_', blocked_by/@thread_hash, '.html')"/>
|
146
|
-
</xsl:attribute>
|
147
|
-
<xsl:attribute name="title">
|
148
|
-
<xsl:value-of select="blocked_by/@name" />
|
149
|
-
</xsl:attribute>
|
150
|
-
Parked on <xsl:value-of select="blocked_by/@thread_id"/>
|
151
|
-
</a>
|
115
|
+
No Stack
|
152
116
|
</xsl:otherwise>
|
153
117
|
</xsl:choose>
|
154
|
-
</
|
155
|
-
</
|
156
|
-
<xsl:when test="state='B'">
|
157
|
-
<td class="blocked">
|
158
|
-
<a target="_blank">
|
159
|
-
<xsl:attribute name="href">
|
160
|
-
<xsl:value-of select="concat('thread_', blocked_by/@thread_hash, '.html')"/>
|
161
|
-
</xsl:attribute>
|
162
|
-
<xsl:attribute name="title">
|
163
|
-
<xsl:value-of select="blocked_by/@name" />
|
164
|
-
</xsl:attribute>
|
165
|
-
Blocked by <xsl:value-of select="blocked_by/@thread_id"/>
|
166
|
-
</a>
|
167
|
-
</td>
|
168
|
-
</xsl:when>
|
169
|
-
<xsl:otherwise>
|
170
|
-
<td><xsl:value-of select="state"/></td>
|
171
|
-
</xsl:otherwise>
|
172
|
-
</xsl:choose>
|
173
|
-
<td>
|
118
|
+
</div>
|
119
|
+
</td>
|
174
120
|
<xsl:choose>
|
175
|
-
|
176
|
-
|
177
|
-
<xsl:
|
178
|
-
<
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
<
|
183
|
-
<xsl:
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
121
|
+
<xsl:when test="state='CW'">
|
122
|
+
<td class="waiting">
|
123
|
+
<xsl:choose>
|
124
|
+
<xsl:when test="blocked_by=''">
|
125
|
+
Waiting on condition
|
126
|
+
</xsl:when>
|
127
|
+
<xsl:otherwise>
|
128
|
+
<a target="_blank">
|
129
|
+
<xsl:attribute name="href">
|
130
|
+
<xsl:value-of select="concat('thread_', blocked_by/@thread_hash, '.html')"/>
|
131
|
+
</xsl:attribute>
|
132
|
+
<xsl:attribute name="title">
|
133
|
+
<xsl:value-of select="blocked_by/@name" />
|
134
|
+
</xsl:attribute>
|
135
|
+
Waiting for <xsl:value-of select="blocked_by/@thread_id"/>
|
136
|
+
</a>
|
137
|
+
</xsl:otherwise>
|
138
|
+
</xsl:choose>
|
139
|
+
</td>
|
140
|
+
</xsl:when>
|
141
|
+
<xsl:when test="state='R'">
|
142
|
+
<td class="runnable">Runnable</td>
|
143
|
+
</xsl:when>
|
144
|
+
<xsl:when test="state='P'">
|
145
|
+
<td class="parked">
|
146
|
+
<xsl:choose>
|
147
|
+
<xsl:when test="blocked_by=''">
|
148
|
+
Parked
|
149
|
+
</xsl:when>
|
150
|
+
<xsl:otherwise>
|
151
|
+
<a target="_blank">
|
152
|
+
<xsl:attribute name="href">
|
153
|
+
<xsl:value-of select="concat('thread_', blocked_by/@thread_hash, '.html')"/>
|
154
|
+
</xsl:attribute>
|
155
|
+
<xsl:attribute name="title">
|
156
|
+
<xsl:value-of select="blocked_by/@name" />
|
157
|
+
</xsl:attribute>
|
158
|
+
Parked on <xsl:value-of select="blocked_by/@thread_id"/>
|
159
|
+
</a>
|
160
|
+
</xsl:otherwise>
|
161
|
+
</xsl:choose>
|
162
|
+
</td>
|
163
|
+
</xsl:when>
|
164
|
+
<xsl:when test="state='B'">
|
165
|
+
<td class="blocked">
|
166
|
+
<a target="_blank">
|
167
|
+
<xsl:attribute name="href">
|
168
|
+
<xsl:value-of select="concat('thread_', blocked_by/@thread_hash, '.html')"/>
|
169
|
+
</xsl:attribute>
|
170
|
+
<xsl:attribute name="title">
|
171
|
+
<xsl:value-of select="blocked_by/@name" />
|
172
|
+
</xsl:attribute>
|
173
|
+
Blocked by <xsl:value-of select="blocked_by/@thread_id"/>
|
174
|
+
</a>
|
175
|
+
</td>
|
176
|
+
</xsl:when>
|
177
|
+
<xsl:otherwise>
|
178
|
+
<td><xsl:value-of select="state"/></td>
|
179
|
+
</xsl:otherwise>
|
180
|
+
</xsl:choose>
|
181
|
+
<td>
|
182
|
+
<xsl:choose>
|
183
|
+
<xsl:when test="blocking/thread">
|
184
|
+
blocking:
|
185
|
+
<xsl:for-each select="blocking/thread">
|
186
|
+
<a target="_blank">
|
187
|
+
<xsl:attribute name="href">
|
188
|
+
<xsl:value-of select="concat('thread_', @thread_hash, '.html')"/>
|
189
|
+
</xsl:attribute>
|
190
|
+
<xsl:attribute name="title">
|
191
|
+
<xsl:value-of select="@name" />
|
192
|
+
</xsl:attribute>
|
193
|
+
<xsl:value-of select="@thread_id" />
|
194
|
+
</a>;
|
195
|
+
</xsl:for-each>
|
196
|
+
</xsl:when>
|
197
|
+
</xsl:choose>
|
198
|
+
</td>
|
199
|
+
</tr>
|
200
|
+
</xsl:for-each>
|
201
|
+
</table>
|
202
|
+
</div>
|
194
203
|
</div>
|
195
204
|
</body>
|
196
205
|
<script>loadChart();</script>
|
javacore_analyser/javacore.py
CHANGED
@@ -127,7 +127,8 @@ class Javacore:
|
|
127
127
|
def encode(self, string):
|
128
128
|
bts = str.encode(string, self.get_encoding(), 'ignore')
|
129
129
|
for i in range(0, len(bts)):
|
130
|
-
|
130
|
+
# fix for 'XML Syntax error PCDATA invalid char#405'
|
131
|
+
if bts[i] < 32 and bts[i] != 9 and bts[i] != 10 and bts[i] != 13 and bts[i] != 1:
|
131
132
|
raise CorruptedJavacoreException("Javacore " + self.filename + " is corrupted in line " + string)
|
132
133
|
string = bts.decode('utf-8', 'ignore')
|
133
134
|
return string
|
@@ -145,7 +146,7 @@ class Javacore:
|
|
145
146
|
break
|
146
147
|
line = self.encode(line)
|
147
148
|
if line.startswith(THREAD_INFO):
|
148
|
-
line =
|
149
|
+
line = Javacore.process_thread_name(line, file)
|
149
150
|
snapshot = ThreadSnapshot.create(line, file, self)
|
150
151
|
self.snapshots.append(snapshot)
|
151
152
|
except Exception as e:
|
@@ -158,7 +159,8 @@ class Javacore:
|
|
158
159
|
finally:
|
159
160
|
file.close()
|
160
161
|
|
161
|
-
|
162
|
+
@staticmethod
|
163
|
+
def process_thread_name(line, file):
|
162
164
|
count = line.count('"')
|
163
165
|
if count == 0: return line # anonymous native threads
|
164
166
|
while True:
|
@@ -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,10 +12,11 @@ import shutil
|
|
12
12
|
import sys
|
13
13
|
import tarfile
|
14
14
|
import tempfile
|
15
|
-
import traceback
|
16
15
|
import zipfile
|
17
16
|
|
17
|
+
import importlib_resources
|
18
18
|
import py7zr
|
19
|
+
from importlib_resources.abc import Traversable
|
19
20
|
|
20
21
|
from javacore_analyser import logging_utils
|
21
22
|
from javacore_analyser.constants import DEFAULT_FILE_DELIMITER
|
@@ -63,43 +64,49 @@ def extract_archive(input_archive_filename, output_path):
|
|
63
64
|
|
64
65
|
|
65
66
|
def main():
|
66
|
-
logging_utils.create_console_logging()
|
67
|
-
logging.info("IBM Javacore analyser")
|
68
|
-
logging.info("Python version: " + sys.version)
|
69
|
-
logging.info("Preferred encoding: " + locale.getpreferredencoding())
|
70
|
-
|
71
67
|
parser = argparse.ArgumentParser()
|
72
|
-
parser.add_argument("
|
73
|
-
|
68
|
+
parser.add_argument("input", help="Input javacore file(s) or directory with javacores. "
|
69
|
+
"The javacores can be packed "
|
70
|
+
"into one of the supported archive formats: zip, gz, bz2, lzma, 7z. "
|
71
|
+
"Additional the verbose GC logs from the time "
|
72
|
+
"when the javacores were collected can be added. "
|
73
|
+
"See doc: https://github.com/IBM/javacore-analyser/wiki")
|
74
|
+
parser.add_argument("output", help="Name of directory where report will be generated")
|
74
75
|
parser.add_argument("--separator",
|
75
76
|
help='Input files separator (default "' + DEFAULT_FILE_DELIMITER + '")',
|
76
77
|
default=DEFAULT_FILE_DELIMITER)
|
77
78
|
args = parser.parse_args()
|
78
79
|
|
79
|
-
input_param = args.
|
80
|
-
output_param = args.
|
80
|
+
input_param = args.input
|
81
|
+
output_param = args.output
|
81
82
|
files_separator = args.separator
|
82
83
|
|
84
|
+
batch_process(input_param, output_param, files_separator)
|
85
|
+
|
86
|
+
|
87
|
+
def batch_process(input_param, output_param, files_separator=DEFAULT_FILE_DELIMITER):
|
88
|
+
logging_utils.create_console_logging()
|
89
|
+
logging.info("IBM Javacore analyser")
|
90
|
+
logging.info("Python version: " + sys.version)
|
91
|
+
logging.info("Preferred encoding: " + locale.getpreferredencoding())
|
83
92
|
logging.info("Input parameter: " + input_param)
|
84
93
|
logging.info("Report directory: " + output_param)
|
85
|
-
|
94
|
+
output_param = os.path.normpath(output_param)
|
86
95
|
# Needs to be created once output file structure is ready.
|
87
96
|
logging_utils.create_file_logging(output_param)
|
88
|
-
|
89
97
|
# Check whether as input we got list of files or single file
|
90
98
|
# Semicolon is separation mark for list of input files
|
91
99
|
if files_separator in input_param or fnmatch.fnmatch(input_param, '*javacore*.txt'):
|
92
|
-
# Process list of the files (copy all or them to output dir
|
100
|
+
# Process list of the files (copy all or them to output dir)
|
93
101
|
files = input_param.split(files_separator)
|
94
102
|
else:
|
95
103
|
files = [input_param]
|
96
|
-
|
97
104
|
try:
|
105
|
+
files = [os.path.normpath(file) for file in files]
|
98
106
|
process_javacores_and_generate_report_data(files, output_param)
|
99
107
|
except Exception as ex:
|
100
|
-
|
101
|
-
logging.error("Processing was not successful. Correct the problem and try again. Exiting with error 13"
|
102
|
-
exc_info=True)
|
108
|
+
logging.exception(ex)
|
109
|
+
logging.error("Processing was not successful. Correct the problem and try again. Exiting with error 13")
|
103
110
|
exit(13)
|
104
111
|
|
105
112
|
|
@@ -115,12 +122,9 @@ def generate_javecore_set_data(files):
|
|
115
122
|
Returns:
|
116
123
|
- JavacoreSet: Generated JavacoreSet object containing the processed data.
|
117
124
|
"""
|
118
|
-
|
119
|
-
|
125
|
+
javacores_temp_dir = tempfile.TemporaryDirectory()
|
120
126
|
try:
|
121
127
|
# Location when we store extracted archive or copied javacores files
|
122
|
-
javacores_temp_dir = tempfile.TemporaryDirectory()
|
123
|
-
|
124
128
|
javacores_temp_dir_name = javacores_temp_dir.name
|
125
129
|
for file in files:
|
126
130
|
if os.path.isdir(file):
|
@@ -137,6 +141,24 @@ def generate_javecore_set_data(files):
|
|
137
141
|
javacores_temp_dir.cleanup()
|
138
142
|
|
139
143
|
|
144
|
+
def create_output_files_structure(output_dir):
|
145
|
+
if not os.path.isdir(output_dir):
|
146
|
+
os.mkdir(output_dir)
|
147
|
+
data_output_dir = os.path.normpath(os.path.join(output_dir, 'data'))
|
148
|
+
if not data_output_dir.startswith(output_dir):
|
149
|
+
raise Exception("Security exception: Uncontrolled data used in path expression")
|
150
|
+
if os.path.isdir(data_output_dir):
|
151
|
+
shutil.rmtree(data_output_dir, ignore_errors=True)
|
152
|
+
logging.info("Data dir: " + data_output_dir)
|
153
|
+
|
154
|
+
style_css_resource: Traversable = importlib_resources.files("javacore_analyser") / "data" / "style.css"
|
155
|
+
data_dir = os.path.dirname(str(style_css_resource))
|
156
|
+
os.mkdir(data_output_dir)
|
157
|
+
shutil.copytree(data_dir, data_output_dir, dirs_exist_ok=True)
|
158
|
+
shutil.copy2(os.path.join(data_output_dir, "html", "processing_data.html"),
|
159
|
+
os.path.join(output_dir, "index.html"))
|
160
|
+
|
161
|
+
|
140
162
|
# Assisted by WCA@IBM
|
141
163
|
# Latest GenAI contribution: ibm/granite-8b-code-instruct
|
142
164
|
def process_javacores_and_generate_report_data(input_files, output_dir):
|
@@ -150,6 +172,7 @@ def process_javacores_and_generate_report_data(input_files, output_dir):
|
|
150
172
|
Returns:
|
151
173
|
None
|
152
174
|
"""
|
175
|
+
create_output_files_structure(output_dir)
|
153
176
|
javacore_set = generate_javecore_set_data(input_files)
|
154
177
|
javacore_set.generate_report_files(output_dir)
|
155
178
|
|