Skip to content

Commit fc09333

Browse files
author
Rustam Sadykov
committed
update docs
1 parent 66a1aeb commit fc09333

File tree

3 files changed

+113
-34
lines changed

3 files changed

+113
-34
lines changed

.github/workflows/night-statistics-monitoring.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,20 @@ jobs:
6363
id: metadata
6464
run: |
6565
echo "::set-output name=commit::$(git rev-parse HEAD)"
66+
echo "::set-output name=short_commit::$(git rev-parse --short HEAD)"
6667
echo "::set-output name=branch::$(git name-rev --name-only HEAD)"
6768
echo "::set-output name=build::$(date +'%Y.%-m')"
6869
6970
- name: Insert metadata
7071
run: |
7172
python monitoring/insert_metadata.py \
72-
$output_stats "$data_path/data-$branch-$date-$timestamp-$commit.json" \
73+
$output_stats "$data_path/data-$branch-$date-$timestamp-$short_commit.json" \
7374
"$commit" "$build"
7475
env:
7576
date: ${{ steps.date.outputs.date }}
7677
timestamp: ${{ steps.date.outputs.timestamp }}
7778
commit: ${{ steps.metadata.outputs.commit }}
79+
short_commit: ${{ steps.metadata.outputs.short_commit }}
7880
branch: ${{ steps.metadata.outputs.branch }}
7981
build: ${{ steps.metadata.outputs.build }}
8082

docs/NightStatisticsMonitoring.md

Lines changed: 97 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
11
# Night Statistics Monitoring
22

3-
## The problem
4-
We want to develop and improve our product and, of course,
5-
there are some changes and its combinations
6-
which, according to some statistics, can make UTBot worse.
3+
## What is the problem?
74

8-
## Monitoring
9-
The main idea is collecting statistics after made changes.
10-
But it takes too long to collect statistics on a huge project
11-
to do it after each push into master.
12-
Thus, we will do it every night when no one makes changes.
5+
As UnitTestBot contributors, we'd like to constantly improve our product. There are many of us introducing code changes simultaneously — unfortunately, some changes or combinations of them may lead to reduced plugin efficiency. To avoid such an unlucky result we need to monitor statistics on test generation performance.
6+
7+
## Why monitor nightly?
8+
9+
It would be great to collect statistics as soon as the contributor changes the code. In case you have a huge project it takes too long to run the monitoring system after each push into master.
10+
Thus, we decided to do it every night when (hopefully!) no one makes changes.
11+
12+
## How do we collect statistics?
13+
14+
To find the algorithm you can refer to StatisticsMonitoring.kt. Shortly speaking, it is based on ContestEstimator.kt, which runs test generation on the sample projects and then compile the resulting tests. We repeat the whole process several times to reduce measurement error.
15+
16+
## Statistics monitoring usage
1317

1418
### Collecting statistics
15-
Collecting statistics StatisticsMonitoring.kt based on ContestEstimator.kt
16-
that runs testcase generation on projects, then compile generated tests.
17-
We run it several times. Input arguments: `<output json>`.
18-
Output stats format: json, array of object with statistics after each running try.
1919

20-
More about statistic: Statistics.kt.
20+
To run statistics monitoring you have to specify the name of the json output file.
21+
22+
Input arguments: `<output json>`.
23+
24+
Output format: you get the json file, which contains an array of objects with statistics on each run.
25+
26+
More about each statistic: Statistics.kt.
2127

2228
More about monitoring settings: MonitoringSettings.kt.
2329

24-
Example input:
30+
Input example:
31+
2532
```
2633
stats.json
2734
```
28-
Example output:
35+
36+
Output example (the result of three runs during one night):
37+
2938
```json
3039
[
3140
{
@@ -79,24 +88,71 @@ Example output:
7988
]
8089
```
8190

82-
### Transforming, aggregating and rendering statistics
83-
Transforming adds total coverage statistics and timestamp.
84-
After that all collected statistics are aggregated by average function.
85-
Then history updates by aggregated statistics and rendered into 2 pictures:
86-
- coverage graph - graph with coverage statistics.
87-
- quantitative graph - graph with other quantitative statistics.
91+
### Metadata and summarising
92+
93+
We can summarise collected statistics by averaging to get statistics more precisely.
94+
95+
In addition, we need more information about the environment and versions used to collect statistics for better interpretation and analysis.
8896

97+
You can find script insert_metadata.py to do tasks described before.
8998

90-
Script: draw_stats_graphs.py.
91-
Input arguments: `<history file> <new stats file> <output coverage graph> <output quantitative graph>`.
92-
We use our repository as database for statistics history.
93-
History format file: json, array of objects with collected statistics.
99+
Input arguments: `<stats file> <output file> <commit hash> <build number>`.
94100

95-
Example input:
101+
Output format: you get the json file, which contains object with summarised statistics and metadata.
102+
103+
Input example:
96104
```
97-
monitoring/history.json stats.json monitoring/coverage_graph.png monitoring/quantitative_graph.png
105+
stats.json data/data-main-2022-08-17-1660740407-66a1aeb6.json 66a1aeb6 2022.8
98106
```
99-
Example output:
107+
108+
Output example:
109+
```json
110+
{
111+
"classes_for_generation": 20.0,
112+
"testcases_generated": 1764.3333333333333,
113+
"classes_without_problems": 12.333333333333334,
114+
"classes_canceled_by_timeout": 2.0,
115+
"total_methods_for_generation": 519.0,
116+
"methods_with_at_least_one_testcase_generated": 394.3333333333333,
117+
"methods_with_exceptions": 45.333333333333336,
118+
"suspicious_methods": 55.333333333333336,
119+
"test_classes_failed_to_compile": 0.0,
120+
"avg_coverage": 62.480721428256736,
121+
"total_coverage": 56.84739152087949,
122+
"total_coverage_by_fuzzing": 41.60749728061026,
123+
"total_coverage_by_concolic": 44.420096905766805,
124+
"metadata": {
125+
"commit_hash": "66a1aeb6",
126+
"build_number": "2022.8",
127+
"environment": {
128+
"host": "host",
129+
"OS": "Windows version 10.0.19043",
130+
"java_version": "openjdk version \"1.8.0_322\"\r\nOpenJDK Runtime Environment Corretto-8.322.06.1 (build 1.8.0_322-b06)\r\nOpenJDK 64-Bit Server VM Corretto-8.322.06.1 (build 25.322-b06, mixed mode)\r\n",
131+
"gradle_version": "Gradle 7.4",
132+
"JAVA_HOME": "D:\\Java\\jdk",
133+
"KOTLIN_HOME": "D:\\Kotlin\\kotlinc",
134+
"PATH": "D:\\gradle-7.4\\bin;D:\\Java\\jre\\bin;"
135+
}
136+
}
137+
}
138+
```
139+
140+
### Aggregating
141+
142+
Script build_aggregated_data.py creates a file with an array of statistics collected during specified period. It can be needed for visualisation or analyzing some statistics as max, min, median etc.
143+
144+
Input arguments: `<input data dir> <output file> <timestamp from> <timestamp to>`.
145+
146+
Required name format of file with data: `*-<timestamp>-<commit hash>.json`.
147+
148+
Output format: you get the json file, which contains an array of objects with statistics collected during specified period.
149+
150+
Input example:
151+
```
152+
./data aggregated_data.json 0 1660740407
153+
```
154+
155+
Output example:
100156
```json
101157
[
102158
{
@@ -113,11 +169,21 @@ Example output:
113169
"total_coverage": 56.84739152087949,
114170
"total_coverage_by_fuzzing": 41.60749728061026,
115171
"total_coverage_by_concolic": 44.420096905766805,
116-
"timestamp": 1660202621883
172+
"timestamp": 1660740407
117173
}
118174
]
119175
```
120176

121-
### Grafana
177+
### Datastorage structure
178+
179+
Our repository is used as database for collected statistics.
180+
181+
There are 2 branches: monitoring-data, monitoring-aggregated-data.
182+
183+
monitoring-data branch is used as a storage for raw collected statistics with metadata. Filename format: `data-<branch>-<yyyy>-<mm>-<dd>-<timestamp>-<short commit hash>.json`
184+
185+
monitoring-aggregated-data branch is used as a storage for aggregated statistics. Specified period is one month. Filename format: `aggregated-data-<yyyy>-<mm>-<dd>.json`
186+
187+
### Grafana (TODO: in process)
122188
Also, we can use [Grafana](https://monitoring.utbot.org) for more dynamic and detailed statistics visualization.
123189
Grafana pulls data from our repository automatically by GitHub API.

monitoring/insert_metadata.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
import re
23
import subprocess
34
from collections import defaultdict
45
from os import environ
@@ -44,19 +45,29 @@ def transform_and_combine_stats(stats_list):
4445

4546
def try_get_output(*args):
4647
try:
47-
return subprocess.check_output(args, stderr=subprocess.STDOUT).decode()
48+
return subprocess.check_output(args, stderr=subprocess.STDOUT, shell=True).decode()
4849
except Exception as e:
4950
print(f'Error in command "{" ".join(args)}":\n\t{e}')
5051
return None
5152

5253

54+
def parse_gradle_version(s):
55+
if s is None:
56+
return None
57+
regex = re.compile(r'^\s*(Gradle [.\d]+)\s*$', re.MULTILINE)
58+
result = regex.search(s)
59+
if result is None:
60+
return None
61+
return result.group(1)
62+
63+
5364
def build_environment_data():
5465
uname_result = uname()
5566
environment = {
5667
'host': uname_result.node,
5768
'OS': f'{uname_result.system} version {uname_result.version}',
5869
'java_version': try_get_output('java', '-version'),
59-
'gradle_version': try_get_output('gradle', '--version'),
70+
'gradle_version': parse_gradle_version(try_get_output('gradle', '--version')),
6071
'JAVA_HOME': environ.get('JAVA_HOME'),
6172
'KOTLIN_HOME': environ.get('KOTLIN_HOME'),
6273
'PATH': environ.get('PATH'),

0 commit comments

Comments
 (0)