run.sh is the general entry point to create a dashboard.
It takes one concatenated log file and calls the individual steps sequentially:
log_processing/process_log_file.shturns the log into a table and looks up the geolocations.data_processing/conda_stats.py,github_stats.pyandpypi_stats.pyfetch the download and contribution statistics.create_report.Rcreates all plots and tables and rendersreporting/report.Rmd.
$ /path/to/scripts/run.sh seqan-combined.logThe name of the log file has to start with seqan- or openms- (lower case), which selects the project.
The report has a ZIP button for an archive of the output directory.
By default, it links the archive that Jenkins creates for a directory.
With --local, run.sh creates the archive itself and the button links it:
$ /path/to/scripts/run.sh --local seqan-combined.logAll output is created in the current working directory:
| Path | Content |
|---|---|
intermediate_output_<project>/ |
all.log, ips.txt and geolocations.csv from step 1 |
output_<project>/report_<date>.html |
The dashboard |
output_<project>/index.html |
Forwards to the latest dashboard |
output_<project>/monthly_*_<date>.tsv |
Statistics fetched in step 2 |
output_<project>/*_<date>.{pdf,png,tsv} |
Plots and tables of the report |
output_<project>/*_<year>_<date>.{pdf,png,tsv} |
Plots and tables of one year |
output_<project>/*_per_year_<date>.tsv |
Values per year of the plots over time |
output_<project>/<Project>_<date>.zip |
With --local: archive of output_<project>/ without other zips |
<date> is the current date for the report, the fetched statistics, the citations and the download and contribution tables,
and the last day of the log for all plots and tables of the log.
Keep the files in output_<project>/ together: the report embeds the plots, but its download buttons link to the individual files.
index.html is a file that forwards to the report (not a symlink), so it survives copying, e.g. with scp.
The report and index.html have a robots meta tag (noindex, nofollow) against indexing by search engines.
Other files (PNG, PDF, TSV, zip) cannot have one; the web server has to send an X-Robots-Tag header for them.
Viewing the report requires an internet connection for the table library and the map tiles.
The worldmap, the top 10 applications, the distribution of countries and cities, and the daily and weekly usage have a tab
for all data of the log and a tab for each year from 2023 (FIRST_YEAR in config/config.R) to the current year.
The tab of a year shows the report for a log that contains only the calls of this year; years without calls have no tab.
The plots over time (general usage, new unique users, unique users, total calls) show all data and have a TSV per year
with the same rows as the download tables (see below). Its values are the sums of the rows of the plot's TSV, so an IP address
counts in the sum of the monthly unique users once for each month in which it has a call.
The monthly plots include the last month of the log, even if the log ends before the end of the month.
The report describes how each number is computed.
Step 2 skips a source if the file with the current date is already in output_<project>/.
Running run.sh again on the same day therefore does not fetch the statistics again, unless --force is given.
| File | Content |
|---|---|
config/config.py |
GitHub repositories and conda/PyPI packages of each project |
config/package_data.yaml |
Catalog for the conda statistics |
config/requirements.txt |
Python dependencies |
config/r-requirements.txt |
R dependencies |
../tooltags/<project>_tooltags.tsv |
Tag of each tool, used by the "General Usage" plot |
config/config.py defines for each project:
library_repos: GitHub repositories that count as library. All other repositories of the GitHub organization count as app.conda_packages_map,pypi_packages_map: Packages that count as library or app. Packages that are not listed are not counted.
Tools without an entry in the tool tags are tagged extern.
| Source | Fetched by | Access |
|---|---|---|
| Conda downloads | conda_stats.py |
Public anaconda-package-data S3 bucket, cached in ${TMPDIR:-/tmp}/s3fs_cache |
| PyPI downloads | pypi_stats.py |
Public ClickHouse demo server |
| GitHub downloads | github_stats.py |
GraphQL API, requires a token |
| GitHub issues and PRs | github_stats.py |
GraphQL API, requires a token |
| Citations | plotting/citations.R |
Google Scholar |
| Geolocations | log_processing/get_ip_addresses.py |
Local database ../database/IP2LOCATION-LITE-DB5.BIN |
The fetched statistics cover the years from 2023 (FIRST_YEAR in config/config.R and data_processing/py/github_shared.py) to the current year.
The download and contribution tables show each full year from 2023 on, the fourth quarter of the previous year to the third quarter of the current year, and the current year.
GitHub only reports a total per release, so a release's downloads are distributed evenly over the time until the next release of the same repository (or up to the fetch date for the latest release).
The GitHub statistics require a personal access token in the environment:
$ export GITHUB_PAT="github_pat_[...]"Without the token, GitHub statistics are not collected, because the rate limit for unauthenticated queries would be hit.
github_stats.py then writes placeholder files with a value of -1 for each month, so that the report can still be created.
These placeholders show up in the report as negative numbers: each GitHub column shows -12 for each period, and Total_Downloads is reduced by 12.
The placeholder files count as existing statistics for the current date.
To collect GitHub statistics after a run without a token, run run.sh --force or delete output_<project>/monthly_github_* first.
The input is an access log in combined log format. Only the IP address, the date and the request are evaluated:
<ip> - - [<date>:<time> <offset>] "GET /check/<who>_<os>_<cpu>_<app>_<version> HTTP/1.1" ...
For example, /check/SeqAn3_Linux_64_needle_1.0.3 has SeqAn3 as who, Linux as os, 64 as cpu, needle as app and 1.0.3 as version.
process_log_file.sh writes these columns to all.log: calls, date, ip, app, version, cpu, os, who and clustered.
- Lines containing a term from
EXCLUDED_TERMS(e.g.,test_version_check) and lines that do not match this format (e.g., without anx.y.zversion) are dropped. - Identical rows are merged: an app counts once per day for each combination of IP address, version, CPU mode, OS and
who. clusteredis set if the previous row has the same date, app, version and the same first two octets of the IP address. The rows are sorted as bytes (LC_ALL=C), so the result does not depend on the locale.data_processing/load.Rremoves these rows from the statistics and reports them as cluster calls in the top 10 plots. The cluster users of an app are the IP addresses whose calls of the app are all cluster calls.- OS names are normalized;
unknowncounts asLinux.
| Path | Content |
|---|---|
config/ |
Configuration, see above |
log_processing/ |
Step 1 |
data_processing/ |
Step 2 (*_stats.py with helpers in py/) and R code to load the data for step 3 |
plotting/ |
R code for the plots |
reporting/ |
R Markdown source of the report and its assets |