javacore-analyser 2.1rc5__py3-none-any.whl → 2.2rc1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- Blue Theme
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.classList.remove('hide');
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 > timestamp;
130
+ endingPoint = timestamp;
129
131
  }
130
132
 
131
133
  coresTimeRange['startTime'] = startingPoint;
@@ -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 - 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
- <div id="memusagedoc" style="display:none;">
359
- This chart shows all the garbage collections that happened between the time
360
- of the first and the last javacore in the data set.
361
- Garbage collections that happened before the first
362
- or after the last javacore generation time are not included.
363
- <ul>
364
- <li><strong>Heap Usage</strong>
365
- is the available Java heap memory over time,
366
- based on the garbage collection data from the verbose GC log files.
367
- </li>
368
- <li><strong>Total Heap</strong>
369
- is the maximum size of the Java heap, configured by using the Xmx Java argument,
370
- expressed in megabytes.
371
- </li>
372
- </ul>
373
- </div>
374
- <div id="systemresources_myChartGC" class="chart-container hide">
375
- <canvas id="myChartGC" height="200"></canvas>
376
- </div>
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 - 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
- create_output_files_structure(output_dir)
173
- javacore_set = generate_javecore_set_data(input_files)
174
- javacore_set.generate_report_files(output_dir)
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
- global reports_dir
136
- reports_dir = args.reports_dir
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 - 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=" file"):
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)
@@ -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.1rc5
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
+ ![GitHub License](https://img.shields.io/github/license/IBM/javacore-analyser)
244
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/javacore-analyser)
245
+ ![GitHub contributors](https://img.shields.io/github/contributors/IBM/javacore-analyser)
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
  [![Build Status](https://app.travis-ci.com/IBM/javacore-analyser.svg?token=w3i4X11XppEi2tJQsxDb&branch=main)](https://app.travis-ci.com/IBM/javacore-analyser)
248
+ ![GitHub last commit](https://img.shields.io/github/last-commit/IBM/javacore-analyser)
249
+ ![GitHub Release Date](https://img.shields.io/github/release-date/IBM/javacore-analyser)
250
+ ![GitHub commit activity](https://img.shields.io/github/commit-activity/t/IBM/javacore-analyser)
251
+ ![GitHub Issues or Pull Requests](https://img.shields.io/github/issues-pr/IBM/javacore-analyser)
252
+ ![GitHub Issues or Pull Requests](https://img.shields.io/github/issues-pr-closed/IBM/javacore-analyser)
253
+ ![PyPI - Downloads](https://img.shields.io/pypi/dm/javacore-analyser)
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: `javacore-analyser-batch <input-data> <generated-reports-dir>`
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=500 --reports-dir=/data/reports_dir`
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
- The first parameter set the port to use by application. If not specified, 5000 will be used.
298
- The second parameter sets where the reports need to be stored. If not set, then the `reports` dir will be created in current location.
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
- Now you can type (http://localhost:5000/).
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=g6xVPYFDHTaXDbaruyMRUrD3g2IlJK3Ht-XUzHv3LoQ,6802
8
- javacore_analyser/javacore_analyser_web.py,sha256=Ef91ZTI5TBaJPJhl0FtzrFHvzJNPLe07fmvbvik3OJQ,5788
9
- javacore_analyser/javacore_set.py,sha256=YM6ZKUhbfqzjuKE5y7Jy19Hbl-BSLA1i5gIsP7NbX38,31241
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=LLJ-PS2maOkP6zfW-RBGoEoHQBI99Reejb1tqpZispY,6872
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=YzHl0NSnfRik4ar6AInp7pZ_re1rirQy6L5jqdbKoKg,2246
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=mI0RCGd6G5GOKSG7BPagp0N58xipSjPXUKvrcHJ4h1Q,7528
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=CMbSqte7Ln0hP9ZScESGdIDfWEmxJwvfLZjDfYNc1Sg,8427
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=XEwgf0qfXL1fXjj-X5iYYwt-D0cPjI9mLjhTmRvyNnk,49697
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.1rc5.dist-info/METADATA,sha256=CMlVgoGP1Fnpof2ycHYf2Auj6XOLRdrO5Q7Jcgr5oVo,21226
42
- javacore_analyser-2.1rc5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
- javacore_analyser-2.1rc5.dist-info/entry_points.txt,sha256=W3S799zI58g5-jWMsC3wY9xksz21LPEMYOILv8sayfM,160
44
- javacore_analyser-2.1rc5.dist-info/licenses/LICENSE,sha256=xllut76FgcGL5zbIRvuRc7aezPbvlMUTWJPsVr2Sugg,11358
45
- javacore_analyser-2.1rc5.dist-info/RECORD,,
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,,