javacore-analyser 2.0rc3__tar.gz → 2.1rc5__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. javacore_analyser-2.1rc5/.travis.yml +33 -0
  2. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/CONTRIBUTING.md +22 -3
  3. javacore_analyser-2.1rc5/Dockerfile +15 -0
  4. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/PKG-INFO +24 -14
  5. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/README.md +21 -12
  6. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/abstract_snapshot_collection.py +2 -2
  7. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/constants.py +2 -1
  8. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/expand.js +2 -0
  9. javacore_analyser-2.1rc5/src/javacore_analyser/data/html/processing_data.html +17 -0
  10. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/search.js +22 -0
  11. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/javacore.py +5 -3
  12. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/javacore_analyser_batch.py +34 -14
  13. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/javacore_analyser_web.py +58 -26
  14. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/javacore_set.py +44 -34
  15. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/snapshot_collection_collection.py +5 -3
  16. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/stack_trace.py +2 -2
  17. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/stack_trace_element.py +1 -1
  18. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/thread_snapshot.py +3 -2
  19. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/tips.py +5 -3
  20. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/verbose_gc.py +4 -1
  21. javacore_analyser-2.0rc3/.travis.yml +0 -10
  22. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  23. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  24. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/.github/dco.yml +0 -0
  25. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/.gitignore +0 -0
  26. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/CHANGELOG.md +0 -0
  27. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/CODE_OF_CONDUCT.md +0 -0
  28. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/LICENSE +0 -0
  29. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/MAINTAINERS.md +0 -0
  30. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/REQUIREMENTS.md +0 -0
  31. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/SECURITY.md +0 -0
  32. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/docs/ClassDiagram.png +0 -0
  33. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/docs/dom_example.py +0 -0
  34. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/pyproject.toml +0 -0
  35. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/requirements.txt +0 -0
  36. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/__init__.py +0 -0
  37. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/code_snapshot_collection.py +0 -0
  38. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/chart.js +0 -0
  39. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/chartjs-adapter-date-fns.bundle.min.js +0 -0
  40. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/jq.css +0 -0
  41. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/jquery.mark.min.js +0 -0
  42. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/jquery.min.js +0 -0
  43. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/jquery.tablesorter.min.js +0 -0
  44. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/jquery.tablesorter.widgets.min.js +0 -0
  45. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/sorting.js +0 -0
  46. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/theme.blue.css +0 -0
  47. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/theme.default.min.css +0 -0
  48. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/jquery/wait2scripts.js +0 -0
  49. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/style.css +0 -0
  50. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/xml/index.xml +0 -0
  51. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/xml/javacores/javacore.xml +0 -0
  52. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/xml/javacores/javacore.xsl +0 -0
  53. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/xml/report.xsl +0 -0
  54. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/xml/threads/thread.xml +0 -0
  55. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/data/xml/threads/thread.xsl +0 -0
  56. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/java_thread.py +0 -0
  57. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/logging_utils.py +0 -0
  58. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/snapshot_collection.py +0 -0
  59. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/stack_trace_kind.py +0 -0
  60. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/src/javacore_analyser/templates/index.html +0 -0
  61. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/__init__.py +0 -0
  62. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/archive_without_javacores.zip +0 -0
  63. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores/aaa-javacore.20220606.114458.32888.0001.txt +0 -0
  64. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores/aaa-javacore.20220606.114502.32888.0002.txt +0 -0
  65. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores-corrupted.zip +0 -0
  66. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores-starting-aaa.zip +0 -0
  67. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores.7z +0 -0
  68. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores.tar.bz2 +0 -0
  69. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores.tar.gz +0 -0
  70. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores.tgz +0 -0
  71. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores.zip +0 -0
  72. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/archives/javacores_with_invalid_chars.zip +0 -0
  73. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/issue129/javacore.20230602.091848.83156.0001.txt +0 -0
  74. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/issue129/javacore.20230602.091853.83156.0002.txt +0 -0
  75. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114458.32888.0001.txt +0 -0
  76. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114502.32888.0002.txt +0 -0
  77. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114506.32888.0003.txt +0 -0
  78. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114513.32888.0004.txt +0 -0
  79. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114516.32888.0005.txt +0 -0
  80. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114900.32888.0006.txt +0 -0
  81. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114907.32888.0007.txt +0 -0
  82. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114912.32888.0008.txt +0 -0
  83. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114931.32888.0009.txt +0 -0
  84. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114947.32888.0010.txt +0 -0
  85. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114948.32888.0011.txt +0 -0
  86. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.20220606.114949.32888.0012.txt +0 -0
  87. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/javacore.wrong.corr +0 -0
  88. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/verbosegc.230105.19308.txt.001 +0 -0
  89. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/verbosegc.230413.19984.txt.001 +0 -0
  90. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/javacores/verbosegc.230420.33424.txt.001 +0 -0
  91. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/quotationMarks/javacore.20230830.134339.30220.0001.txt +0 -0
  92. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/quotationMarks/javacore.20230830.134339.30220.0002.txt +0 -0
  93. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGc/verbosegc.230105.19308.txt.001 +0 -0
  94. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGc/verbosegc.230413.19984.txt.001 +0 -0
  95. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGc/verbosegc.230420.33424.txt.001 +0 -0
  96. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores/javacore.20230602.091848.83156.0001.txt +0 -0
  97. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores/javacore.20230602.091853.83156.0002.txt +0 -0
  98. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores/javacore.20230602.092423.83156.0003.txt +0 -0
  99. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores/javacore.20230602.092537.83156.0004.txt +0 -0
  100. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores/javacore.20230602.092604.83156.0005.txt +0 -0
  101. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores/verbosegc.230602.61164.txt.001 +0 -0
  102. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores/verbosegc.230602.83156.txt.001 +0 -0
  103. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/data/verboseGcJavacores.zip +0 -0
  104. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_code_snapshot_collection.py +0 -0
  105. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_gc_collection.py +0 -0
  106. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_java_thread.py +0 -0
  107. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_javacore.py +0 -0
  108. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_javacore_analyser.py +0 -0
  109. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_javacore_set.py +0 -0
  110. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_stack_trace.py +0 -0
  111. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_stack_trace_element.py +0 -0
  112. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_thread_snapshot.py +0 -0
  113. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_tips.py +0 -0
  114. {javacore_analyser-2.0rc3 → javacore_analyser-2.1rc5}/test/test_verbose_gc_parser.py +0 -0
@@ -0,0 +1,33 @@
1
+ language: python
2
+ python:
3
+ - "3.9"
4
+ before_install:
5
+ - pip install 'urllib3<2.0' #Enforce SSL version to be able to run twine
6
+ - pip install -U pytest
7
+ - pip install -U build
8
+ - pip install -U twine
9
+ install:
10
+ - pip install -r requirements.txt
11
+ - pip install .
12
+ env:
13
+ global:
14
+ - PYTHONPATH=src:test
15
+ script:
16
+ # - pytest
17
+ - python -m build
18
+ deploy:
19
+ - provider: script
20
+ #script: python -m twine upload --skip-existing --verbose --password $TWINE_TEST_TOKEN --repository testpypi dist/* #test instance
21
+ script: python -m twine upload --skip-existing --verbose --password $TWINE_PROD_TOKEN dist/* #production instance.
22
+ on:
23
+ all_branches: true # uncomment for testing purposes
24
+ # branch: prod # uncomment on production
25
+ tags: true # We need to consider if we want to publish all versions or every build (which should not be an issue
26
+ - provider: releases
27
+ edge: true
28
+ draft: true
29
+ file: dist/*
30
+ on:
31
+ all_branches: true # uncomment for testing purposes
32
+ # branch: prod # uncomment on production
33
+ tags: true # We need to consider if we want to publish all versions or every build (which should not be an issue
@@ -85,9 +85,9 @@ Change the second parameter to the directory where you want the output report be
85
85
 
86
86
  To run web application:
87
87
  1. Right click on **javacore_analyser_web.py** directory in **Project** view and select **Modify Run Configuration...**.
88
- 2. Add the following **Environmental variables:**
89
- * **DEBUG:True**
90
- * **REPORTS_DIR:/tmp/web_reports**
88
+ 2. Add the following parameters:
89
+ **debug=True reports_dir=/tmp/web_reports**
90
+
91
91
  You can change the report dir to the location when you want to store the report.
92
92
  The application will start on http://localhost:5000
93
93
 
@@ -96,6 +96,25 @@ To run web application:
96
96
  Follow the steps from [Packaging projects](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
97
97
  Currently Chris has an API keys for test and production pypi
98
98
 
99
+ ## Build container localy
100
+ To build a container:
101
+ `podman build -t javacore-analyser .`
102
+
103
+ or
104
+
105
+ `docker build -t javacore-analyser .`
106
+
107
+ To start the container:
108
+ `podman run -it --rm --name javacore-analyser --mount type=bind,src="local-dir-on-fs",target=/reports -p 5001:5000 javacore-analyser`
109
+
110
+ or
111
+
112
+ `docker run -it --rm --name javacore-analyser --mount type=bind,src="local-dir-on-fs",target=/reports -p 5001:5000 javacore-analyser`
113
+
114
+ `src` parameter specifies where you want to store reports locally
115
+ `-p` specifies port mapping. The application in container is running on port 5000. You can map it to another port on
116
+ your machine (5001 in this example).
117
+
99
118
  ## Testing
100
119
  As default the tests in Pycharm are ran in the current selected directory. However we want to run them in main
101
120
  directory of the tool (**javacore-analyser** directory, not **test** directory).
@@ -0,0 +1,15 @@
1
+ #
2
+ # Copyright IBM Corp. 2024 - 2024
3
+ # SPDX-License-Identifier: Apache-2.0
4
+ #
5
+
6
+ FROM python:3
7
+
8
+ EXPOSE 5000/tcp
9
+ ENV REPORTS_DIR=/reports
10
+ RUN mkdir /reports
11
+ VOLUME ["/reports"]
12
+
13
+ RUN pip install --no-cache-dir javacore-analyser
14
+
15
+ CMD [ "javacore_analyser_web" ]
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: javacore_analyser
3
- Version: 2.0rc3
3
+ Version: 2.1rc5
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
@@ -209,6 +209,7 @@ License: Apache License
209
209
  See the License for the specific language governing permissions and
210
210
  limitations under the License.
211
211
 
212
+ License-File: LICENSE
212
213
  Classifier: Development Status :: 5 - Production/Stable
213
214
  Classifier: Environment :: Console
214
215
  Classifier: Environment :: Web Environment
@@ -280,9 +281,7 @@ This is recommended for geeks only:
280
281
  #### Running cmd application:
281
282
  1. Install application if not done yet
282
283
  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)
283
- 3. Install the requirements using pip:
284
- `pip install requirements.txt`
285
- 4. Run the following command from cmd: `javacore-analyser-batch <input-data> <generated-reports-dir>`
284
+ 3. Run the following command from cmd: `javacore-analyser-batch <input-data> <generated-reports-dir>`
286
285
  Where `<input-data>` is one of the following:
287
286
  * The directory containing javacores and optionally verbose gc
288
287
  * Archive (7z, zip, tar.gz, tar.bz2) containing the same
@@ -292,17 +291,28 @@ You can type the following command to obtain the help:
292
291
 
293
292
  #### Running web application:
294
293
  1. Repeat steps 1-3 from cmd application
295
- 2. OPTIONAL: set the following variables:
296
- ```
297
- export REPORTS_DIR=/tmp/reports
298
- export PORT=5000
299
- ```
300
- The first parameter sets where the reports need to be stored. If not set, then the `reports` dir will be created in current location.
301
- The first parameter set the port to use by application. If not specified, 5000 will be used.
302
- 3. Execute the following command from cmd:
303
- `javacore_analyser_web`
294
+ 2. Execute the following command from cmd:
295
+ `javacore_analyser_web --port=500 --reports-dir=/data/reports_dir`
296
+
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.
304
299
 
305
300
  Now you can type (http://localhost:5000/).
301
+
302
+ ### Running container image
303
+ There is an unofficial Docker/Podman container managed by one of projects developers. Use the following command
304
+ to start it:
305
+
306
+ `podman run -it --rm --name javacore-analyser --mount type=bind,src="/local-reports-dir",target=/reports -p 5001:5000 ghcr.io/kkazmierczyk/javacore-analyser:latest`
307
+
308
+ or
309
+ `docker run -it --rm --name javacore-analyser --mount type=bind,src="/local-reports-dir",target=/reports -p 5001:5000 ghcr.io/kkazmierczyk/javacore-analyser:latest`
310
+
311
+ The `mount` option specifies where you want locally to store the reports. The reports in the container are stored in
312
+ `/reports` directory. If you remove mount option, the application will work but the reports will not persist after
313
+ restart.
314
+ The application is running in the container on port 5000. By using `-p 5001:5000` option, you specify to map container
315
+ port 5000 to port 5001 on your machine. Therefore the application will be available under `http://localhost:5001/`.
306
316
 
307
317
  <!-- The following are OPTIONAL, but strongly suggested to have in your repository. -->
308
318
  <!--
@@ -43,9 +43,7 @@ This is recommended for geeks only:
43
43
  #### Running cmd application:
44
44
  1. Install application if not done yet
45
45
  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)
46
- 3. Install the requirements using pip:
47
- `pip install requirements.txt`
48
- 4. Run the following command from cmd: `javacore-analyser-batch <input-data> <generated-reports-dir>`
46
+ 3. Run the following command from cmd: `javacore-analyser-batch <input-data> <generated-reports-dir>`
49
47
  Where `<input-data>` is one of the following:
50
48
  * The directory containing javacores and optionally verbose gc
51
49
  * Archive (7z, zip, tar.gz, tar.bz2) containing the same
@@ -55,17 +53,28 @@ You can type the following command to obtain the help:
55
53
 
56
54
  #### Running web application:
57
55
  1. Repeat steps 1-3 from cmd application
58
- 2. OPTIONAL: set the following variables:
59
- ```
60
- export REPORTS_DIR=/tmp/reports
61
- export PORT=5000
62
- ```
63
- The first parameter sets where the reports need to be stored. If not set, then the `reports` dir will be created in current location.
64
- The first parameter set the port to use by application. If not specified, 5000 will be used.
65
- 3. Execute the following command from cmd:
66
- `javacore_analyser_web`
56
+ 2. Execute the following command from cmd:
57
+ `javacore_analyser_web --port=500 --reports-dir=/data/reports_dir`
58
+
59
+ The first parameter set the port to use by application. If not specified, 5000 will be used.
60
+ The second parameter sets where the reports need to be stored. If not set, then the `reports` dir will be created in current location.
67
61
 
68
62
  Now you can type (http://localhost:5000/).
63
+
64
+ ### Running container image
65
+ There is an unofficial Docker/Podman container managed by one of projects developers. Use the following command
66
+ to start it:
67
+
68
+ `podman run -it --rm --name javacore-analyser --mount type=bind,src="/local-reports-dir",target=/reports -p 5001:5000 ghcr.io/kkazmierczyk/javacore-analyser:latest`
69
+
70
+ or
71
+ `docker run -it --rm --name javacore-analyser --mount type=bind,src="/local-reports-dir",target=/reports -p 5001:5000 ghcr.io/kkazmierczyk/javacore-analyser:latest`
72
+
73
+ The `mount` option specifies where you want locally to store the reports. The reports in the container are stored in
74
+ `/reports` directory. If you remove mount option, the application will work but the reports will not persist after
75
+ restart.
76
+ The application is running in the container on port 5000. By using `-p 5001:5000` option, you specify to map container
77
+ port 5000 to port 5001 on your machine. Therefore the application will be available under `http://localhost:5001/`.
69
78
 
70
79
  <!-- The following are OPTIONAL, but strongly suggested to have in your repository. -->
71
80
  <!--
@@ -59,7 +59,7 @@ class AbstractSnapshotCollection(abc.ABC):
59
59
  self.thread_snapshots.append(snapshot)
60
60
 
61
61
  def index_of(self, snapshot):
62
- for i in range(len(self.thread_snapshotssnaps)):
62
+ for i in range(len(self.thread_snapshots)):
63
63
  if self.thread_snapshots[i] == snapshot: return i
64
64
  return -1
65
65
 
@@ -142,7 +142,7 @@ class AbstractSnapshotCollection(abc.ABC):
142
142
  result = 0
143
143
  for i in self.thread_snapshots:
144
144
  el = i.get_java_stack_depth()
145
- if el>result:
145
+ if el > result:
146
146
  result = el
147
147
  return result
148
148
 
@@ -30,10 +30,11 @@ ENCODING = '1TICHARSET'
30
30
  DATA_OUTPUT_SUBDIR = '/data/'
31
31
  DEFAULT_FILE_DELIMITER = ';'
32
32
 
33
- MIN_JAVACORE_SIZE = 5 * 1024 # Minimal Javacore size in bytes
33
+ MIN_JAVACORE_SIZE = 5 * 1024 # Minimal Javacore size in bytes
34
34
 
35
35
  DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
36
36
 
37
37
  # Web application constants
38
38
  DEFAULT_REPORTS_DIR = "reports"
39
39
  DEFAULT_PORT = 5000
40
+ TEMP_DIR = "temp_data" # Folder to store temporary data for creating reports
@@ -15,6 +15,8 @@ $('.show').click(function () {
15
15
  }
16
16
  });
17
17
 
18
+
19
+
18
20
  function expand_it(whichEl, link) {
19
21
  whichEl.style.display = (whichEl.style.display == "none") ? "" : "none";
20
22
  //if (link) {
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+
3
+ <!--
4
+ # Copyright IBM Corp. 2024 - 2024
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ -->
7
+
8
+ <html lang="en">
9
+ <head>
10
+ <meta http-equiv="refresh" content="30" /> <!-- Refresh this page every 30s until generated page appears -->
11
+ <meta charset="UTF-8">
12
+ <title>The page is being generated</title>
13
+ </head>
14
+ <body>
15
+ <h1>The page is being generated. Once it is ready, it will appear here.</h1>
16
+ </body>
17
+ </html>
@@ -49,10 +49,32 @@ $(function() {
49
49
  searchInNode(rootNode, searchTerm);
50
50
  }
51
51
 
52
+ function processChild(child) {
53
+ try {
54
+ if (isDomNode(child) && child.classList.contains('toggle_expand')) {
55
+ for (i = 0; i < child.childNodes.length; ++i) {
56
+ grandchild = child.childNodes[i];
57
+ if (isDomNode(grandchild) && grandchild.text == '[+] Expand') {
58
+ grandchild.text = '[-] Collapse';
59
+ }
60
+ }
61
+ }
62
+ } catch(err) {
63
+ console.log(err);
64
+ }
65
+ }
66
+
52
67
  function searchInNode(node, searchTerm) {
53
68
  if (!isDomNode(node)) return;
54
69
  if (node.textContent.toUpperCase().match(searchTerm.toUpperCase())) {
55
70
  // expand the node here
71
+ if (!node.classList.contains('show-all')) {
72
+ node.classList.add('show-all');
73
+ for (i = 0; i < node.childNodes.length; ++i) {
74
+ child = node.childNodes[i];
75
+ processChild(child);
76
+ }
77
+ }
56
78
  if (node.getAttribute('style') && node.style.display == "none") {
57
79
  node.style.display = "";
58
80
  }
@@ -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:
@@ -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
@@ -69,15 +70,20 @@ def main():
69
70
  logging.info("Preferred encoding: " + locale.getpreferredencoding())
70
71
 
71
72
  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")
73
+ parser.add_argument("input", help="Input javacore file(s) or directory with javacores. "
74
+ "The javacores can be packed "
75
+ "into one of the supported archive formats: zip, gz, bz2, lzma, 7z. "
76
+ "Additional the verbose GC logs from the time "
77
+ "when the javacores were collected can be added. "
78
+ "See doc: https://github.com/IBM/javacore-analyser/wiki")
79
+ parser.add_argument("output", help="Name of directory where report will be generated")
74
80
  parser.add_argument("--separator",
75
81
  help='Input files separator (default "' + DEFAULT_FILE_DELIMITER + '")',
76
82
  default=DEFAULT_FILE_DELIMITER)
77
83
  args = parser.parse_args()
78
84
 
79
- input_param = args.input_param
80
- output_param = args.output_param
85
+ input_param = args.input
86
+ output_param = args.output
81
87
  files_separator = args.separator
82
88
 
83
89
  logging.info("Input parameter: " + input_param)
@@ -89,17 +95,15 @@ def main():
89
95
  # Check whether as input we got list of files or single file
90
96
  # Semicolon is separation mark for list of input files
91
97
  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
98
+ # Process list of the files (copy all or them to output dir)
93
99
  files = input_param.split(files_separator)
94
100
  else:
95
101
  files = [input_param]
96
-
97
102
  try:
98
103
  process_javacores_and_generate_report_data(files, output_param)
99
104
  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)
105
+ logging.exception(ex)
106
+ logging.error("Processing was not successful. Correct the problem and try again. Exiting with error 13")
103
107
  exit(13)
104
108
 
105
109
 
@@ -115,12 +119,9 @@ def generate_javecore_set_data(files):
115
119
  Returns:
116
120
  - JavacoreSet: Generated JavacoreSet object containing the processed data.
117
121
  """
118
-
119
-
122
+ javacores_temp_dir = tempfile.TemporaryDirectory()
120
123
  try:
121
124
  # Location when we store extracted archive or copied javacores files
122
- javacores_temp_dir = tempfile.TemporaryDirectory()
123
-
124
125
  javacores_temp_dir_name = javacores_temp_dir.name
125
126
  for file in files:
126
127
  if os.path.isdir(file):
@@ -137,6 +138,24 @@ def generate_javecore_set_data(files):
137
138
  javacores_temp_dir.cleanup()
138
139
 
139
140
 
141
+ def create_output_files_structure(output_dir):
142
+ if not os.path.isdir(output_dir):
143
+ os.mkdir(output_dir)
144
+ data_output_dir = os.path.normpath(os.path.join(output_dir, 'data'))
145
+ if not data_output_dir.startswith(output_dir):
146
+ raise Exception("Security exception: Uncontrolled data used in path expression")
147
+ if os.path.isdir(data_output_dir):
148
+ shutil.rmtree(data_output_dir, ignore_errors=True)
149
+ logging.info("Data dir: " + data_output_dir)
150
+
151
+ style_css_resource: Traversable = importlib_resources.files("javacore_analyser") / "data" / "style.css"
152
+ data_dir = os.path.dirname(str(style_css_resource))
153
+ os.mkdir(data_output_dir)
154
+ shutil.copytree(data_dir, data_output_dir, dirs_exist_ok=True)
155
+ shutil.copy2(os.path.join(data_output_dir, "html", "processing_data.html"),
156
+ os.path.join(output_dir, "index.html"))
157
+
158
+
140
159
  # Assisted by WCA@IBM
141
160
  # Latest GenAI contribution: ibm/granite-8b-code-instruct
142
161
  def process_javacores_and_generate_report_data(input_files, output_dir):
@@ -150,6 +169,7 @@ def process_javacores_and_generate_report_data(input_files, output_dir):
150
169
  Returns:
151
170
  None
152
171
  """
172
+ create_output_files_structure(output_dir)
153
173
  javacore_set = generate_javecore_set_data(input_files)
154
174
  javacore_set.generate_report_files(output_dir)
155
175
 
@@ -2,6 +2,7 @@
2
2
  # Copyright IBM Corp. 2024 - 2024
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  #
5
+ import argparse
5
6
  import locale
6
7
  import logging
7
8
  import os
@@ -9,6 +10,7 @@ import re
9
10
  import shutil
10
11
  import sys
11
12
  import tempfile
13
+ import threading
12
14
  import time
13
15
  from pathlib import Path
14
16
 
@@ -16,29 +18,30 @@ from flask import Flask, render_template, request, send_from_directory, redirect
16
18
  from waitress import serve
17
19
 
18
20
  import javacore_analyser.javacore_analyser_batch
19
- from javacore_analyser.constants import DEFAULT_REPORTS_DIR, DEFAULT_PORT
21
+ from javacore_analyser.constants import DEFAULT_REPORTS_DIR, DEFAULT_PORT, TEMP_DIR
20
22
  from javacore_analyser.logging_utils import create_console_logging, create_file_logging
21
23
 
22
24
  """
23
25
  To run the application from cmd type:
24
- export REPORTS_DIR=/tmp/reports
26
+
25
27
  flask --app javacore_analyser_web run
26
28
  """
27
29
  app = Flask(__name__)
28
- with app.app_context():
29
- create_console_logging()
30
- logging.info("Javacore analyser")
31
- logging.info("Python version: " + sys.version)
32
- logging.info("Preferred encoding: " + locale.getpreferredencoding())
33
- reports_dir = os.getenv("REPORTS_DIR", DEFAULT_REPORTS_DIR)
34
- logging.info("Reports directory: " + reports_dir)
35
- create_file_logging(reports_dir)
30
+ reports_dir = DEFAULT_REPORTS_DIR
31
+
32
+
33
+ # Assisted by watsonx Code Assistant
34
+ def create_temp_data_in_reports_dir(directory):
35
+ tmp_reports_dir = os.path.join(directory, TEMP_DIR)
36
+ if os.path.isdir(tmp_reports_dir):
37
+ shutil.rmtree(tmp_reports_dir, ignore_errors=True)
38
+ os.mkdir(tmp_reports_dir)
36
39
 
37
40
 
38
41
  @app.route('/')
39
42
  def index():
40
43
  reports = [{"name": Path(f).name, "date": time.ctime(os.path.getctime(f)), "timestamp": os.path.getctime(f)}
41
- for f in os.scandir(reports_dir) if f.is_dir()]
44
+ for f in os.scandir(reports_dir) if f.is_dir() and Path(f).name is not TEMP_DIR]
42
45
  reports.sort(key=lambda item: item["timestamp"], reverse=True)
43
46
  return render_template('index.html', reports=reports)
44
47
 
@@ -50,8 +53,8 @@ def dir_listing(path):
50
53
 
51
54
  @app.route('/zip/<path:path>')
52
55
  def compress(path):
56
+ temp_zip_dir = tempfile.TemporaryDirectory()
53
57
  try:
54
- temp_zip_dir = tempfile.TemporaryDirectory()
55
58
  temp_zip_dir_name = temp_zip_dir.name
56
59
  zip_filename = path + ".zip"
57
60
  report_location = os.path.join(reports_dir, path)
@@ -68,7 +71,7 @@ def compress(path):
68
71
  def delete(path):
69
72
  # Checking if the report exists. This is to prevent attempt to delete any data by deleting any file outside
70
73
  # report dir if you prepare path variable.
71
- reports_list = os.listdir(reports_dir)
74
+ # reports_list = os.listdir(reports_dir)
72
75
  report_location = os.path.normpath(os.path.join(reports_dir, path))
73
76
  if not report_location.startswith(reports_dir):
74
77
  logging.error("Deleted report in report list. Not deleting")
@@ -82,10 +85,19 @@ def delete(path):
82
85
  # Latest GenAI contribution: ibm/granite-20b-code-instruct-v2
83
86
  @app.route('/upload', methods=['POST'])
84
87
  def upload_file():
88
+
89
+ report_name = request.values.get("report_name")
90
+ report_name = re.sub(r'[^a-zA-Z0-9]', '_', report_name)
91
+
92
+ # Create a temporary directory to store uploaded files
93
+ # Note We have to use permanent files and then delete them.
94
+ # tempfile.Temporary_directory function does not work when you want to access files from another threads.
95
+ javacores_temp_dir_name = os.path.normpath(os.path.join(reports_dir, TEMP_DIR, report_name))
96
+ if not javacores_temp_dir_name.startswith(reports_dir):
97
+ raise Exception("Security exception: Uncontrolled data used in path expression")
98
+
85
99
  try:
86
- # Create a temporary directory to store uploaded files
87
- javacores_temp_dir = tempfile.TemporaryDirectory()
88
- javacores_temp_dir_name = javacores_temp_dir.name
100
+ os.mkdir(javacores_temp_dir_name)
89
101
 
90
102
  # Get the list of files from webpage
91
103
  files = request.files.getlist("files")
@@ -97,26 +109,46 @@ def upload_file():
97
109
  file.save(file_name)
98
110
  input_files.append(file_name)
99
111
 
100
- report_name = request.values.get("report_name")
101
- report_name = re.sub(r'[^a-zA-Z0-9]', '_', report_name)
102
-
103
112
  # Process the uploaded file
104
- report_output_dir = reports_dir + '/' + report_name
105
- javacore_analyser.javacore_analyser_batch.process_javacores_and_generate_report_data(input_files,
106
- report_output_dir)
107
-
113
+ report_output_dir = os.path.join(reports_dir, report_name)
114
+ processing_thread = threading.Thread(
115
+ target=javacore_analyser.javacore_analyser_batch.process_javacores_and_generate_report_data,
116
+ name="Processing javacore data", args=(input_files, report_output_dir)
117
+ )
118
+ processing_thread.start()
119
+
120
+ time.sleep(1) # Give 1 second to generate index.html in processing_thread before redirecting
108
121
  return redirect("/reports/" + report_name + "/index.html")
109
122
  finally:
110
- javacores_temp_dir.cleanup()
123
+ shutil.rmtree(javacores_temp_dir_name, ignore_errors=True)
124
+
111
125
 
112
126
  def main():
113
- debug = os.getenv("DEBUG", False)
114
- port = os.getenv("PORT", DEFAULT_PORT)
127
+ parser = argparse.ArgumentParser()
128
+ parser.add_argument("--debug", help="Debug mode. Use only for development", default=False)
129
+ parser.add_argument("--port", help="Port to run application", default=DEFAULT_PORT)
130
+ parser.add_argument("--reports-dir", help="Directory where app reports are stored",
131
+ default=DEFAULT_REPORTS_DIR)
132
+ args = parser.parse_args()
133
+ debug = args.debug
134
+ port = args.port
135
+ global reports_dir
136
+ reports_dir = args.reports_dir
137
+
138
+ create_console_logging()
139
+ logging.info("Javacore analyser")
140
+ logging.info("Python version: " + sys.version)
141
+ logging.info("Preferred encoding: " + locale.getpreferredencoding())
142
+ logging.info("Reports directory: " + reports_dir)
143
+ create_file_logging(reports_dir)
144
+ create_temp_data_in_reports_dir(reports_dir)
145
+
115
146
  if debug:
116
147
  app.run(debug=True, port=port) # Run Flask for development
117
148
  else:
118
149
  serve(app, port=port) # Run Waitress in production
119
150
 
151
+
120
152
  if __name__ == '__main__':
121
153
  """
122
154
  The application passes the following environmental variables: