talp-pages 3.4.0a1__tar.gz
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.
- talp_pages-3.4.0a1/PKG-INFO +97 -0
- talp_pages-3.4.0a1/README.md +68 -0
- talp_pages-3.4.0a1/pyproject.toml +40 -0
- talp_pages-3.4.0a1/talp_pages/__init__.py +0 -0
- talp_pages-3.4.0a1/talp_pages/download_artifacts.py +90 -0
- talp_pages-3.4.0a1/talp_pages/talp_add_to_db.py +97 -0
- talp_pages-3.4.0a1/talp_pages/talp_badge.py +99 -0
- talp_pages-3.4.0a1/talp_pages/talp_common.py +43 -0
- talp_pages-3.4.0a1/talp_pages/talp_pages.py +106 -0
- talp_pages-3.4.0a1/talp_pages/talp_report.py +84 -0
- talp_pages-3.4.0a1/talp_pages/talp_report_ts.py +161 -0
- talp_pages-3.4.0a1/talp_pages/templates/talp_index_page.html +153 -0
- talp_pages-3.4.0a1/talp_pages/templates/talp_index_page.jinja +155 -0
- talp_pages-3.4.0a1/talp_pages/templates/talp_report.html +199 -0
- talp_pages-3.4.0a1/talp_pages/templates/talp_report.jinja +197 -0
- talp_pages-3.4.0a1/talp_pages/templates/talp_report_ts.html +385 -0
- talp_pages-3.4.0a1/talp_pages/templates/talp_time_series.jinja +364 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: talp-pages
|
|
3
|
+
Version: 3.4.0a1
|
|
4
|
+
Summary: Command line tools to generate performance reports using the TALP module of DLB
|
|
5
|
+
Home-page: https://pm.bsc.es/gitlab/dlb/talp-pages/
|
|
6
|
+
License: GPL-3.0-only
|
|
7
|
+
Keywords: HPC,Performance Analysis,Profiling,Continuous Performance Analysis
|
|
8
|
+
Author: Valentin Seitz
|
|
9
|
+
Author-email: valentin.seitz@bsc.es
|
|
10
|
+
Maintainer: Valentin Seitz
|
|
11
|
+
Maintainer-email: valentin.seitz@bsc.es
|
|
12
|
+
Requires-Python: >=3.9,<4.0
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
22
|
+
Classifier: Topic :: System :: Distributed Computing
|
|
23
|
+
Requires-Dist: jinja2 (>=3.1.4,<4.0.0)
|
|
24
|
+
Requires-Dist: pandas (>=2.2.2,<3.0.0)
|
|
25
|
+
Requires-Dist: python-gitlab (>=4.4.0,<5.0.0)
|
|
26
|
+
Project-URL: Repository, https://pm.bsc.es/gitlab/dlb/talp-pages/
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
{height=250px}
|
|
30
|
+
|
|
31
|
+
# Talp Pages
|
|
32
|
+
|
|
33
|
+
TALP Pages is a collection of Python scripts to postprocess the `json` outputs of [DLB TALP](https://pm.bsc.es/ftp/dlb/doc/user-guide/intro.html#talp-tracking-application-live-performance) and Gitlab pipeline snippets [that can be included](https://docs.gitlab.com/ee/ci/yaml/#include) in your project.
|
|
34
|
+
This makes it easy to integrate TALP into your CI/CD setup and run Continous Benchmarking without having to code up your own solution.
|
|
35
|
+
|
|
36
|
+
**We provide:**
|
|
37
|
+
|
|
38
|
+
- talp_pages: Command line tool to generate static html pages
|
|
39
|
+
- Artifact management: A easy way to use Gitlab Artifacts to generate time series data plots.
|
|
40
|
+
- Reusable Jobs that easily integrate into a existing Gitlab CI enviroment
|
|
41
|
+
|
|
42
|
+
## Use python package
|
|
43
|
+
|
|
44
|
+
Talp-Pages is written in Python (3.9+). We rely on [poetry](https://python-poetry.org/) for packaging.
|
|
45
|
+
To use, simply install via:
|
|
46
|
+
|
|
47
|
+
```pip install talp-pages```
|
|
48
|
+
|
|
49
|
+
From there you should have the following command-line tools available:
|
|
50
|
+
|
|
51
|
+
- `talp_report`
|
|
52
|
+
- `talp_add_to_db`
|
|
53
|
+
- `talp_badge`
|
|
54
|
+
- `talp_report_ts`
|
|
55
|
+
- `talp_pages`
|
|
56
|
+
- `talp_download_artifacts`
|
|
57
|
+
|
|
58
|
+
## Use Gitlab Jobs
|
|
59
|
+
|
|
60
|
+
This section currently is not completly done, but we provide examples on how to use the jobs below:
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
|
|
64
|
+
talp-performance-run:
|
|
65
|
+
stage: performance
|
|
66
|
+
image: python:3.12-bullseye
|
|
67
|
+
script:
|
|
68
|
+
- python generate_talp_json.py
|
|
69
|
+
artifacts:
|
|
70
|
+
paths:
|
|
71
|
+
- talp.json
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
include:
|
|
75
|
+
- remote: https://pm.bsc.es/gitlab/dlb/talp-pages/-/raw/main/templates/add-to-db/template.yml
|
|
76
|
+
inputs:
|
|
77
|
+
stage: deploy
|
|
78
|
+
generating_job: talp-performance-run
|
|
79
|
+
talp_output: ./talp.json
|
|
80
|
+
enviroment: production
|
|
81
|
+
gitlab_url: https://gitlab.com
|
|
82
|
+
project_name: valentin.seitz1/sample-application
|
|
83
|
+
dlb_home: ./dlb_talp
|
|
84
|
+
job_name: talp-create-artifacts
|
|
85
|
+
- remote: https://pm.bsc.es/gitlab/dlb/talp-pages/-/raw/main/templates/generate-html/template.yml
|
|
86
|
+
inputs:
|
|
87
|
+
stage: deploy
|
|
88
|
+
generating_job: talp-create-artifacts
|
|
89
|
+
enviroment: production
|
|
90
|
+
dlb_home: ./dlb_talp
|
|
91
|
+
job_name: talp-gen-html
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
Talp-Pages is available under the General Public License v3.0.
|
|
97
|
+
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{height=250px}
|
|
2
|
+
|
|
3
|
+
# Talp Pages
|
|
4
|
+
|
|
5
|
+
TALP Pages is a collection of Python scripts to postprocess the `json` outputs of [DLB TALP](https://pm.bsc.es/ftp/dlb/doc/user-guide/intro.html#talp-tracking-application-live-performance) and Gitlab pipeline snippets [that can be included](https://docs.gitlab.com/ee/ci/yaml/#include) in your project.
|
|
6
|
+
This makes it easy to integrate TALP into your CI/CD setup and run Continous Benchmarking without having to code up your own solution.
|
|
7
|
+
|
|
8
|
+
**We provide:**
|
|
9
|
+
|
|
10
|
+
- talp_pages: Command line tool to generate static html pages
|
|
11
|
+
- Artifact management: A easy way to use Gitlab Artifacts to generate time series data plots.
|
|
12
|
+
- Reusable Jobs that easily integrate into a existing Gitlab CI enviroment
|
|
13
|
+
|
|
14
|
+
## Use python package
|
|
15
|
+
|
|
16
|
+
Talp-Pages is written in Python (3.9+). We rely on [poetry](https://python-poetry.org/) for packaging.
|
|
17
|
+
To use, simply install via:
|
|
18
|
+
|
|
19
|
+
```pip install talp-pages```
|
|
20
|
+
|
|
21
|
+
From there you should have the following command-line tools available:
|
|
22
|
+
|
|
23
|
+
- `talp_report`
|
|
24
|
+
- `talp_add_to_db`
|
|
25
|
+
- `talp_badge`
|
|
26
|
+
- `talp_report_ts`
|
|
27
|
+
- `talp_pages`
|
|
28
|
+
- `talp_download_artifacts`
|
|
29
|
+
|
|
30
|
+
## Use Gitlab Jobs
|
|
31
|
+
|
|
32
|
+
This section currently is not completly done, but we provide examples on how to use the jobs below:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
|
|
36
|
+
talp-performance-run:
|
|
37
|
+
stage: performance
|
|
38
|
+
image: python:3.12-bullseye
|
|
39
|
+
script:
|
|
40
|
+
- python generate_talp_json.py
|
|
41
|
+
artifacts:
|
|
42
|
+
paths:
|
|
43
|
+
- talp.json
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
include:
|
|
47
|
+
- remote: https://pm.bsc.es/gitlab/dlb/talp-pages/-/raw/main/templates/add-to-db/template.yml
|
|
48
|
+
inputs:
|
|
49
|
+
stage: deploy
|
|
50
|
+
generating_job: talp-performance-run
|
|
51
|
+
talp_output: ./talp.json
|
|
52
|
+
enviroment: production
|
|
53
|
+
gitlab_url: https://gitlab.com
|
|
54
|
+
project_name: valentin.seitz1/sample-application
|
|
55
|
+
dlb_home: ./dlb_talp
|
|
56
|
+
job_name: talp-create-artifacts
|
|
57
|
+
- remote: https://pm.bsc.es/gitlab/dlb/talp-pages/-/raw/main/templates/generate-html/template.yml
|
|
58
|
+
inputs:
|
|
59
|
+
stage: deploy
|
|
60
|
+
generating_job: talp-create-artifacts
|
|
61
|
+
enviroment: production
|
|
62
|
+
dlb_home: ./dlb_talp
|
|
63
|
+
job_name: talp-gen-html
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
Talp-Pages is available under the General Public License v3.0.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "talp-pages"
|
|
3
|
+
version = "3.4.0-alpha1"
|
|
4
|
+
description = "Command line tools to generate performance reports using the TALP module of DLB"
|
|
5
|
+
authors = ["Valentin Seitz <valentin.seitz@bsc.es>"]
|
|
6
|
+
maintainers = ["Valentin Seitz <valentin.seitz@bsc.es>"]
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
license = "GPL-3.0-only"
|
|
9
|
+
keywords = ["HPC", "Performance Analysis","Profiling","Continuous Performance Analysis"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Intended Audience :: Science/Research",
|
|
12
|
+
"Operating System :: OS Independent",
|
|
13
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
14
|
+
"Topic :: System :: Distributed Computing"
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
homepage = "https://pm.bsc.es/gitlab/dlb/talp-pages/"
|
|
18
|
+
repository= "https://pm.bsc.es/gitlab/dlb/talp-pages/"
|
|
19
|
+
include = [
|
|
20
|
+
"talp_pages/templates/*.jinja"
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[tool.poetry.dependencies]
|
|
24
|
+
python = "^3.9"
|
|
25
|
+
python-gitlab = "^4.4.0"
|
|
26
|
+
jinja2 = "^3.1.4"
|
|
27
|
+
pandas = "^2.2.2"
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
[tool.poetry.scripts]
|
|
31
|
+
talp_add_to_db = 'talp_pages.talp_add_to_db:main'
|
|
32
|
+
talp_report = 'talp_pages.talp_report:main'
|
|
33
|
+
talp_badge = 'talp_pages.talp_badge:main'
|
|
34
|
+
talp_report_ts = 'talp_pages.talp_report_ts:main'
|
|
35
|
+
talp_pages = 'talp_pages.talp_pages:main'
|
|
36
|
+
talp_download_artifacts = 'talp_pages.download_artifacts:main'
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = ["poetry-core"]
|
|
40
|
+
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import argparse
|
|
5
|
+
import gitlab
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
Script to automagically choose a suitable authentication method and download the .zip archive of the last sucessfull
|
|
10
|
+
execution of that jobname on the branch: ref-name
|
|
11
|
+
Requires python-gitlab to be installed
|
|
12
|
+
|
|
13
|
+
Default behaviour: create empty zip file
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def download_artifacts(gl, project_name, job_name, ref_name, gitlab_token=None, output_file=None):
|
|
18
|
+
try:
|
|
19
|
+
project = gl.projects.get(project_name)
|
|
20
|
+
except gitlab.exceptions.GitlabGetError as e:
|
|
21
|
+
logging.error("Failed to get project details: %s", str(e))
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
logging.debug("Found project ID: %s", project.id)
|
|
25
|
+
|
|
26
|
+
# Get artifacts for the job
|
|
27
|
+
try:
|
|
28
|
+
artifacts_file = project.artifacts.download(
|
|
29
|
+
ref_name=ref_name, job=job_name.strip())
|
|
30
|
+
logging.info("Artifacts downloaded successfully: %s", output_file)
|
|
31
|
+
except Exception as e:
|
|
32
|
+
logging.critical(
|
|
33
|
+
"Wasnt able to download artifacts, continue with a empty zip directory")
|
|
34
|
+
artifacts_file = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
|
35
|
+
|
|
36
|
+
with open(output_file, 'wb') as f:
|
|
37
|
+
f.write(artifacts_file)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def main():
|
|
41
|
+
parser = argparse.ArgumentParser(
|
|
42
|
+
description="Download artifacts from the latest successful GitLab CI job")
|
|
43
|
+
parser.add_argument(
|
|
44
|
+
"--gitlab-url", help="GitLab URL (the thing before /api/*)", required=True)
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"--project-name", help="GitLab project name (format: namespace/project)", required=True)
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"--job-name", help="Name of the GitLab CI job from which to download the artifact", required=True)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--output-file", help="Output file name for downloaded artifacts", required=True)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--ref-name", help="GitLab branch name", default="main")
|
|
53
|
+
parser.add_argument(
|
|
54
|
+
"--gitlab-token", help="Personal GitLab access token (if not specified it will try to use a job_token)")
|
|
55
|
+
parser.add_argument(
|
|
56
|
+
"--log-level", help="Logging level (DEBUG, INFO, WARNING, ERROR)", default="INFO")
|
|
57
|
+
|
|
58
|
+
args = parser.parse_args()
|
|
59
|
+
|
|
60
|
+
log_level = getattr(logging, args.log_level.upper(), None)
|
|
61
|
+
if not isinstance(log_level, int):
|
|
62
|
+
raise ValueError("Invalid log level: %s" % args.log_level)
|
|
63
|
+
|
|
64
|
+
logging.basicConfig(level=log_level)
|
|
65
|
+
job_gitlab_token = None
|
|
66
|
+
gitlab_token = None
|
|
67
|
+
|
|
68
|
+
if args.gitlab_token:
|
|
69
|
+
gitlab_token = args.gitlab_token
|
|
70
|
+
else:
|
|
71
|
+
job_gitlab_token = os.getenv("CI_JOB_TOKEN")
|
|
72
|
+
print(job_gitlab_token)
|
|
73
|
+
logging.debug("Using the CI_JOB_TOKEN variant")
|
|
74
|
+
|
|
75
|
+
gl = None
|
|
76
|
+
if gitlab_token:
|
|
77
|
+
gl = gitlab.Gitlab(args.gitlab_url, private_token=gitlab_token)
|
|
78
|
+
gl.auth()
|
|
79
|
+
elif job_gitlab_token:
|
|
80
|
+
gl = gitlab.Gitlab(args.gitlab_url, job_token=job_gitlab_token)
|
|
81
|
+
logging.debug("Using the CI_JOB_TOKEN variant")
|
|
82
|
+
else:
|
|
83
|
+
gl = gitlab.Gitlab(args.gitlab_url)
|
|
84
|
+
|
|
85
|
+
download_artifacts(gl, args.project_name, args.job_name,
|
|
86
|
+
args.ref_name, args.gitlab_token, args.output_file,)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
if __name__ == "__main__":
|
|
90
|
+
main()
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# myapp/app.py
|
|
2
|
+
import argparse
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
import sqlite3
|
|
8
|
+
import logging
|
|
9
|
+
from .talp_common import TALP_TABLE_NAME, TALP_TABLE_COLUMNS_WITH_DATATYPES, TALP_TABLE_COLUMNS
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Function to insert data into the SQLite database
|
|
13
|
+
def insert_data(conn, timestamp, talp_output, metadata):
|
|
14
|
+
# Connect to the SQLite database
|
|
15
|
+
cursor = conn.cursor()
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
# Create a table if it doesn't exist
|
|
19
|
+
cursor.execute(
|
|
20
|
+
f"CREATE TABLE IF NOT EXISTS {TALP_TABLE_NAME} {TALP_TABLE_COLUMNS_WITH_DATATYPES}")
|
|
21
|
+
|
|
22
|
+
# Create an index on the timestamp column
|
|
23
|
+
cursor.execute(
|
|
24
|
+
f"CREATE INDEX IF NOT EXISTS idx_timestamp ON {TALP_TABLE_NAME} (timestamp)")
|
|
25
|
+
|
|
26
|
+
# Convert JSON objects to string format
|
|
27
|
+
|
|
28
|
+
# Insert data into the table
|
|
29
|
+
cursor.execute(f"INSERT INTO {TALP_TABLE_NAME} {TALP_TABLE_COLUMNS} VALUES (?, ?, ?)", (
|
|
30
|
+
timestamp, json.dumps(talp_output), json.dumps(metadata)))
|
|
31
|
+
|
|
32
|
+
# Commit changes and close the connection
|
|
33
|
+
conn.commit()
|
|
34
|
+
logging.debug("Data inserted successfully")
|
|
35
|
+
except sqlite3.Error as e:
|
|
36
|
+
logging.critical("ERROR inserting data:", e)
|
|
37
|
+
finally:
|
|
38
|
+
# Close the connection
|
|
39
|
+
conn.close()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main():
|
|
43
|
+
# Parse command-line arguments
|
|
44
|
+
parser = argparse.ArgumentParser(
|
|
45
|
+
description='Add talp.json to the local time series database')
|
|
46
|
+
parser.add_argument('-i', '--input', dest='talp',
|
|
47
|
+
help='talp.json file to be added', required=True)
|
|
48
|
+
parser.add_argument('-m', '--metadata', dest='metadata',
|
|
49
|
+
help='metadata.json file to be added', required=False)
|
|
50
|
+
parser.add_argument('-db', '--database', dest='database',
|
|
51
|
+
help='TALP.db file. If not specified a new one will be generated', required=False)
|
|
52
|
+
# TODO add timestamp mechanism
|
|
53
|
+
args = parser.parse_args()
|
|
54
|
+
|
|
55
|
+
# Check if the JSON file exists
|
|
56
|
+
if not os.path.exists(args.talp):
|
|
57
|
+
logging.error(f"The specified JSON file '{args.talp}' does not exist.")
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
if args.metadata:
|
|
61
|
+
if not os.path.exists(args.metadata):
|
|
62
|
+
logging.error(
|
|
63
|
+
f"The specified JSON file '{args.metadata}' does not exist.")
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
# Set output
|
|
67
|
+
if args.database:
|
|
68
|
+
DB_FILE = args.database
|
|
69
|
+
else:
|
|
70
|
+
DB_FILE = "TALP.db"
|
|
71
|
+
|
|
72
|
+
# Connect to database
|
|
73
|
+
conn = sqlite3.connect(DB_FILE)
|
|
74
|
+
|
|
75
|
+
current_timestamp = datetime.now()
|
|
76
|
+
|
|
77
|
+
with open(args.talp, 'r') as json_file:
|
|
78
|
+
try:
|
|
79
|
+
talp_output = json.load(json_file)
|
|
80
|
+
except json.JSONDecodeError as e:
|
|
81
|
+
logging.error(f"Error decoding JSON: {e}")
|
|
82
|
+
return
|
|
83
|
+
if args.metadata:
|
|
84
|
+
with open(args.metadata, 'r') as json_file:
|
|
85
|
+
try:
|
|
86
|
+
metadata = json.load(json_file)
|
|
87
|
+
except json.JSONDecodeError as e:
|
|
88
|
+
logging.error(f"Error decoding JSON: {e}")
|
|
89
|
+
return
|
|
90
|
+
else:
|
|
91
|
+
metadata = {}
|
|
92
|
+
|
|
93
|
+
insert_data(conn, current_timestamp, talp_output, metadata)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
main()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
from urllib.request import urlopen, Request
|
|
7
|
+
import logging
|
|
8
|
+
from .talp_common import TALP_POP_METRICS_KEY,TALP_DEFAULT_REGION_NAME
|
|
9
|
+
|
|
10
|
+
class TalpBadge:
|
|
11
|
+
def __init__(self, talp_file):
|
|
12
|
+
# Now directly try to create a connection
|
|
13
|
+
with open(talp_file, 'r') as json_file:
|
|
14
|
+
# dont catch exception, but fail
|
|
15
|
+
self.raw_data = json.load(json_file)
|
|
16
|
+
|
|
17
|
+
logging.debug(f"Created TalpReport and read the json: {self.raw_data}")
|
|
18
|
+
# do some sanity checks
|
|
19
|
+
if not self.raw_data[TALP_POP_METRICS_KEY]:
|
|
20
|
+
logging.error(f"No {TALP_POP_METRICS_KEY} found in {talp_file}. Try re-running DLB with arguments --talp --talp-summary=pop-metrics --talp-file={talp_file}")
|
|
21
|
+
raise Exception(f"No {TALP_POP_METRICS_KEY} found")
|
|
22
|
+
|
|
23
|
+
def get_badge_svg(self):
|
|
24
|
+
|
|
25
|
+
parallel_efficiency = None
|
|
26
|
+
pop_metric_regions = self.raw_data[TALP_POP_METRICS_KEY]
|
|
27
|
+
for region in pop_metric_regions:
|
|
28
|
+
if region['name'] == TALP_DEFAULT_REGION_NAME:
|
|
29
|
+
parallel_efficiency = region['parallelEfficiency']
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
if not parallel_efficiency:
|
|
33
|
+
raise Exception(f"Could not find {TALP_DEFAULT_REGION_NAME} in provided json")
|
|
34
|
+
|
|
35
|
+
parallel_efficiency = round(parallel_efficiency, 2)
|
|
36
|
+
|
|
37
|
+
if parallel_efficiency < 0.6:
|
|
38
|
+
bagde_url = f"https://img.shields.io/badge/Parallel_efficiency-{parallel_efficiency}-red"
|
|
39
|
+
elif parallel_efficiency < 0.8:
|
|
40
|
+
bagde_url = f"https://img.shields.io/badge/Parallel_efficiency-{parallel_efficiency}-orange"
|
|
41
|
+
else:
|
|
42
|
+
bagde_url = f"https://img.shields.io/badge/Parallel_efficiency-{parallel_efficiency}-green"
|
|
43
|
+
|
|
44
|
+
return urlopen(Request(url=bagde_url, headers={'User-Agent': 'Mozilla'})).read()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _validate_inputs(args):
|
|
49
|
+
output_file=None
|
|
50
|
+
input_file=None
|
|
51
|
+
# Check if the JSON file exists
|
|
52
|
+
if not os.path.exists(args.input):
|
|
53
|
+
raise Exception(
|
|
54
|
+
f"Error: The specified JSON file '{args.json_file}' does not exist.")
|
|
55
|
+
else:
|
|
56
|
+
input_file= args.input
|
|
57
|
+
# Set output
|
|
58
|
+
if args.output:
|
|
59
|
+
output_file = args.output
|
|
60
|
+
if not args.output.endswith('.svg'):
|
|
61
|
+
output_file += ".svg"
|
|
62
|
+
logging.info(f"Appending .svg to '{args.output}'")
|
|
63
|
+
# Check if the HTML file exists
|
|
64
|
+
if os.path.exists(args.output):
|
|
65
|
+
logging.info(f"Overwriting '{args.output}'")
|
|
66
|
+
else:
|
|
67
|
+
output_file = args.input.replace(".json", "")
|
|
68
|
+
output_file += ".svg"
|
|
69
|
+
|
|
70
|
+
return output_file,input_file
|
|
71
|
+
|
|
72
|
+
def main():
|
|
73
|
+
# Parse command-line arguments
|
|
74
|
+
parser = argparse.ArgumentParser(
|
|
75
|
+
description='Render a SVG badge that can be used in pipelines using shields.io. Therefore internet access is required')
|
|
76
|
+
parser.add_argument('-i', '--input', dest='input', help='Path to the TALP JSON file')
|
|
77
|
+
parser.add_argument('-o', '--output', dest='output',
|
|
78
|
+
help='Name of the svg file beeing generated. If not specified [input].svg will be chosen', required=False)
|
|
79
|
+
|
|
80
|
+
# Parsing arguments
|
|
81
|
+
try:
|
|
82
|
+
args = parser.parse_args()
|
|
83
|
+
output_file, input_file = _validate_inputs(args)
|
|
84
|
+
except Exception as e:
|
|
85
|
+
logging.error(f"When parsing arguments ecountered the following error: {e}")
|
|
86
|
+
parser.print_help()
|
|
87
|
+
exit(1)
|
|
88
|
+
|
|
89
|
+
badge = TalpBadge(input_file)
|
|
90
|
+
rendered_svg = badge.get_badge_svg()
|
|
91
|
+
with open(output_file, 'wb') as f:
|
|
92
|
+
f.write(rendered_svg)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == "__main__":
|
|
99
|
+
main()
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""
|
|
2
|
+
File declaring some global scoped variables we rely to be there in our scrips
|
|
3
|
+
"""
|
|
4
|
+
import pathlib
|
|
5
|
+
from jinja2 import Environment, FileSystemLoader
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
TALP_TABLE_NAME = "talp_data"
|
|
9
|
+
TALP_DB_COLUMN_TALP_OUPUT = "talp_ouput"
|
|
10
|
+
TALP_DB_COLUMN_TIMESTAMP = "timestamp"
|
|
11
|
+
TALP_DB_COLUMN_METADATA = "metadata"
|
|
12
|
+
TALP_DEFAULT_REGION_NAME = "MPI Execution"
|
|
13
|
+
TALP_POP_METRICS_KEY = 'popMetrics'
|
|
14
|
+
|
|
15
|
+
TALP_TEMPLATE_PATH = pathlib.Path(__file__).parent.joinpath('templates').resolve()
|
|
16
|
+
TALP_TABLE_COLUMNS_WITH_DATATYPES = f"({TALP_DB_COLUMN_TIMESTAMP} TIMESTAMP, {TALP_DB_COLUMN_TALP_OUPUT} TEXT, {TALP_DB_COLUMN_METADATA} TEXT)"
|
|
17
|
+
TALP_TABLE_COLUMNS = f"({TALP_DB_COLUMN_TIMESTAMP} ,{TALP_DB_COLUMN_TALP_OUPUT}, {TALP_DB_COLUMN_METADATA})"
|
|
18
|
+
|
|
19
|
+
TALP_PAGES_REPORT_SITE = 'report.html'
|
|
20
|
+
TALP_PAGES_TIME_SERIES_SITE='report_ts.html'
|
|
21
|
+
TALP_PAGES_INDEX_SITE='index.html'
|
|
22
|
+
TALP_PAGES_BAGDE='parallel_effiency.svg'
|
|
23
|
+
|
|
24
|
+
def render_template(directory, template_name, **context):
|
|
25
|
+
# Set up Jinja2 environment and load the template
|
|
26
|
+
env = Environment(loader=FileSystemLoader(directory))
|
|
27
|
+
template = env.get_template(template_name)
|
|
28
|
+
|
|
29
|
+
# Render the template with the provided context
|
|
30
|
+
return template.render(context)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def date_time_to_string(datetime):
|
|
34
|
+
return datetime.strftime("%d.%m.%Y %H:%M")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class TalpRelativeLinks:
|
|
39
|
+
"""Class to bundle the generated links in the html"""
|
|
40
|
+
home: str
|
|
41
|
+
report: str
|
|
42
|
+
report_ts: str
|
|
43
|
+
render_navbar: bool = False
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import os
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
from .talp_common import TALP_PAGES_INDEX_SITE, TALP_PAGES_REPORT_SITE, TALP_PAGES_TIME_SERIES_SITE, TALP_PAGES_BAGDE, render_template, TALP_TEMPLATE_PATH, TalpRelativeLinks
|
|
8
|
+
from .talp_badge import TalpBadge
|
|
9
|
+
from .talp_report import TalpReport
|
|
10
|
+
from .talp_report_ts import TalpTimeSeriesReport
|
|
11
|
+
|
|
12
|
+
class TalpIndexPage:
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_html(self,links:TalpRelativeLinks):
|
|
16
|
+
return render_template(
|
|
17
|
+
TALP_TEMPLATE_PATH,
|
|
18
|
+
'talp_index_page.jinja',
|
|
19
|
+
links=vars(links),
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _verify_input(args):
|
|
32
|
+
json_file = None
|
|
33
|
+
db_file = None
|
|
34
|
+
prefix = None
|
|
35
|
+
|
|
36
|
+
# Check if the JSON file exists
|
|
37
|
+
if not os.path.exists(args.json_input):
|
|
38
|
+
logging.error(
|
|
39
|
+
f"The specified JSON file '{args.json_input}' does not exist.")
|
|
40
|
+
raise Exception("Not existing input file")
|
|
41
|
+
else:
|
|
42
|
+
json_file = args.json_input
|
|
43
|
+
|
|
44
|
+
# Check if the SQLITE file exists
|
|
45
|
+
if not os.path.exists(args.db_input):
|
|
46
|
+
logging.error(
|
|
47
|
+
f"The specified SQLITE file '{args.db_input}' does not exist.")
|
|
48
|
+
raise Exception("Not existing input file")
|
|
49
|
+
else:
|
|
50
|
+
db_file = args.db_input
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
prefix = args.prefix
|
|
54
|
+
|
|
55
|
+
return json_file,db_file,prefix
|
|
56
|
+
|
|
57
|
+
def main():
|
|
58
|
+
|
|
59
|
+
def _add_prefix(pref,inp)->str:
|
|
60
|
+
if pref:
|
|
61
|
+
return pref + "_" + inp
|
|
62
|
+
else:
|
|
63
|
+
return inp
|
|
64
|
+
|
|
65
|
+
# Creating the main argument parser
|
|
66
|
+
parser = argparse.ArgumentParser(description='Render the complete static html pages including a index page.' )
|
|
67
|
+
# Adding argument for JSON file
|
|
68
|
+
parser.add_argument('-j', '--json', dest='json_input', help='Path to the TALP JSON file')
|
|
69
|
+
# Adding argument for DB file
|
|
70
|
+
parser.add_argument('-d', '--db', dest='db_input', help='Path to the TALP.db file')
|
|
71
|
+
# Adding argument for prefix
|
|
72
|
+
parser.add_argument('-p', '--prefix', dest='prefix', help=f"Prefix used in front of the (_){TALP_PAGES_REPORT_SITE}, (_){TALP_PAGES_TIME_SERIES_SITE} and (_){TALP_PAGES_INDEX_SITE}", required=False)
|
|
73
|
+
|
|
74
|
+
# Parsing arguments
|
|
75
|
+
try:
|
|
76
|
+
args = parser.parse_args()
|
|
77
|
+
json_file,db_file,prefix = _verify_input(args)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
logging.error(f"When parsing arguments ecountered the following error: {e}")
|
|
80
|
+
parser.print_help()
|
|
81
|
+
exit(1)
|
|
82
|
+
|
|
83
|
+
output_report_ts=_add_prefix(prefix,TALP_PAGES_TIME_SERIES_SITE)
|
|
84
|
+
output_report=_add_prefix(prefix,TALP_PAGES_REPORT_SITE)
|
|
85
|
+
badge_file=_add_prefix(prefix,TALP_PAGES_BAGDE)
|
|
86
|
+
output_index=_add_prefix(prefix,TALP_PAGES_INDEX_SITE)
|
|
87
|
+
links=TalpRelativeLinks(output_index,output_report,output_report_ts,render_navbar=True)
|
|
88
|
+
index = TalpIndexPage()
|
|
89
|
+
report_ts= TalpTimeSeriesReport(db_file)
|
|
90
|
+
report = TalpReport(json_file)
|
|
91
|
+
bagde = TalpBadge(json_file)
|
|
92
|
+
|
|
93
|
+
with open(output_index, 'w') as f:
|
|
94
|
+
f.write(index.get_html(links))
|
|
95
|
+
|
|
96
|
+
with open(output_report_ts, 'w') as f:
|
|
97
|
+
f.write(report_ts.get_html(links))
|
|
98
|
+
|
|
99
|
+
with open(output_report, 'w') as f:
|
|
100
|
+
f.write(report.get_html(links))
|
|
101
|
+
|
|
102
|
+
with open(badge_file, 'wb') as f:
|
|
103
|
+
f.write(bagde.get_badge_svg())
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|