javacore-analyser 2.0rc1__py3-none-any.whl → 2.1__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.
@@ -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
- <p class="right"><a href="../index.html"> Back to Main page </a></p>
28
- <h2>Wait Report for thread: <b><xsl:value-of select="thread_name"/></b></h2>
29
- <xsl:choose>
30
- <xsl:when test="//javacore_count = 1">
31
- System resource utilization data cannot be calculated with only a single javacore.
32
- </xsl:when>
33
- <xsl:otherwise>
34
- <div class="chart-container" height="25%">
35
- <canvas id="myChart" height="100%"></canvas>
36
- </div>
37
- </xsl:otherwise>
38
- </xsl:choose>
39
- <div id="all_threads">
40
- <table id="all_threads_table_thread_xsl">
41
- <thead>
42
- <tr>
43
- <th>Timestamp</th>
44
- <th>Elapsed time (s)</th>
45
- <th>CPU usage (s)</th>
46
- <th>% CPU usage</th>
47
- <th class='sixty'>Stack trace</th>
48
- <th>State</th>
49
- <th>Blocking</th>
50
- </tr>
51
- </thead>
52
- <!-- Snapshot starts here -->
53
- <xsl:for-each select="*[starts-with(name(), 'stack')]">
54
- <tr>
55
- <td>
56
- <a>
57
- <xsl:attribute name="href">
58
- ../javacores/<xsl:value-of select="file_name"/>.html
59
- </xsl:attribute>
60
- <xsl:value-of select='timestamp'/>
61
- </a>
62
- </td>
63
- <xsl:choose>
64
- <xsl:when test="position()=1">
65
- <td>N/A</td>
66
- </xsl:when>
67
- <xsl:otherwise>
68
- <td>
69
- <xsl:value-of select='format-number(elapsed_time, "0.##")'/>
70
- </td>
71
- </xsl:otherwise>
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><xsl:value-of select='format-number(cpu_percentage, "0.#")'/></td>
76
+ <td>
77
+ <xsl:value-of select='format-number(elapsed_time, "0.##")'/>
78
+ </td>
87
79
  </xsl:otherwise>
88
80
  </xsl:choose>
89
- <td class="left">
90
- <div>
91
- <xsl:choose>
92
- <xsl:when test="stack_depth &gt; 0">
93
- <div class="toggle_expand">
94
- <a href="javaScript:;" class="show">[+] Expand</a>
95
- </div>
96
- <p class="stacktrace">
97
- <xsl:for-each select="*[starts-with(name(), 'line')]">
98
- <span>
99
- <xsl:attribute name="class"><xsl:value-of select="@kind"/></xsl:attribute>
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
- No Stack
94
+ <td><xsl:value-of select='format-number(cpu_percentage, "0.#")'/></td>
108
95
  </xsl:otherwise>
109
96
  </xsl:choose>
110
- </div>
111
- </td>
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="blocked_by=''">
140
- Parked
100
+ <xsl:when test="stack_depth &gt; 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
- <a target="_blank">
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
- </td>
155
- </xsl:when>
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
- <xsl:when test="blocking/thread">
176
- blocking:
177
- <xsl:for-each select="blocking/thread">
178
- <a target="_blank">
179
- <xsl:attribute name="href">
180
- <xsl:value-of select="concat('thread_', @thread_hash, '.html')"/>
181
- </xsl:attribute>
182
- <xsl:attribute name="title">
183
- <xsl:value-of select="@name" />
184
- </xsl:attribute>
185
- <xsl:value-of select="@thread_id" />
186
- </a>;
187
- </xsl:for-each>
188
- </xsl:when>
189
- </xsl:choose>
190
- </td>
191
- </tr>
192
- </xsl:for-each>
193
- </table>
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>
@@ -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
- if bts[i] < 32 and bts[i] != 9 and bts[i] != 10 and bts[i] != 13 and bts[i] != 1: # fix for 'XML Syntax error PCDATA invalid char#405'
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 = self.processThreadName(line, file)
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
- def processThreadName(self, line, file):
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 - 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("input_param", help="Input file(s) or directory")
73
- parser.add_argument("output_param", help="Report output directory")
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.input_param
80
- output_param = args.output_param
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
- traceback.print_exc(file=sys.stdout)
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