Skip to content

Commit 5ec6212

Browse files
authored
Merge pull request #6 from Cortze/random-peering
Documentation Update
2 parents 90d488b + cb32c72 commit 5ec6212

File tree

5 files changed

+216
-14
lines changed

5 files changed

+216
-14
lines changed

.gitignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ src/bin
88

99
# Ignore the example folder (personal to each user)
1010
examples/*
11+
# Ignore the example folder (personal to each user)
12+
general-results/*
1113

12-
# Ignore System Files
14+
# Ignore System Files (from MAC)
1315
.DS_Store
1416
._.DS_Store
1517

1618
# ignore the venv
1719
src/analyzer/venv
18-
19-
src/analyzer/dashboard/static/plots

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,21 @@ To use the tool the following tools needs to be installed on the machine:
99

1010
### Usage
1111
The crawler can be easily executed from the `armiarma.sh` file (make sure that is an executable file).
12-
The executable `armiarma.sh` launching shell script supports three different commands that correspond to the main functionalities of the tool.
12+
The executable `armiarma.sh` launching shell script supports five different commands that correspond to the main functionalities of the tool.
1313
Those commands are:
1414

1515
- `./armiarma.sh -h` to display the help text of the tool.
1616
- `./armiarma.sh -c [network] [project-name]` to launch the armiarma crawler on the given network. The given project-name is the name of the folder where the gathered metrics and where all the related information will be saved. The folder will be placed on the `./examples` folder.
1717
- `./armiarma.sh -p [project-name]` to launch the armiarma analyzer over the metrics from the given project. The generted plots of the analysis will be saved on the `./examples/[project-name]/plots` folder.
18+
- `./armiarma.sh -f [network] [project-name] [time]` to launch the armiarma crawler on the given network for the given `time` in minutes. The given project-name is the name of the folder where the gathered metrics and where all the related information will be saved. The folder will be placed on the `./examples` folder. After the crawling for the given time, the analyzer will be launched automatically. The summary results will be saved on the `./examples/[project-name]/plots` folder.
19+
- `./armiarma.sh -o` to launch the armiarma general overview analyzer over the metrics from the projects' folder. The generted results of the analysis will be saved on the `./general-resutls` folder.
1820

1921
```
2022
./armiarma.sh --> -h
2123
'-> -c [network] [project-name]
2224
'-> -p [project-name]
25+
'-> -f [network] [project-name] [time](minutes)
26+
'-> -o
2327
```
2428

2529
The tool will get the Go packages and compile Rumor as generate the virtual env and install the python3 dependencies for the user.

armiarma.sh

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,19 @@ Help()
3030
echo " *Parameters for -p [name]"
3131
echo " -f Run a time specified test, performing the analysis"
3232
echo " of the obtained"
33+
echo " *Parameters for -f [network] [project-name] [time](minutes)"
34+
echo " -o Run the general analysis over the entire projects' folder."
35+
echo ""
3336
echo " Parameters:"
3437
echo " [network] The ETH2 network where the crawler will be running"
3538
echo " Currently supported networks:"
3639
echo " -> mainnet"
3740
echo " [project-name] Specify the name of the folder where the metrics"
3841
echo " and plots will be stored."
3942
echo " Find them on 'armiarma/examples/[project-name]'"
43+
echo " [time] Specific time in minutes to run the crawler, performing afterwards"
44+
echo " the general analysis."
45+
echo ""
4046
echo ""
4147
echo " BSC-ETH2 TEAM"
4248
}
@@ -142,7 +148,7 @@ LaunchCrawler(){
142148
# Move to the example folder
143149
cd "./examples/${folderName}"
144150

145-
# Append the bash env variables to the temp file
151+
# Append the bash env variables to the temp fhiustile
146152
echo "metricsFolder=\"${metricsFolder}\"" >> config.sh
147153
echo "armiarmaPath=\"${folderPath}\"" >> config.sh
148154

@@ -211,7 +217,7 @@ LaunchAnalyzer(){
211217
echo "venv already created"
212218
else
213219
echo "Generating the virtual env"
214-
python -m virtualenv "$VENV"
220+
python3 -m virtualenv "$VENV"
215221
fi
216222
echo ""
217223
# Source the virtual env
@@ -230,7 +236,7 @@ LaunchAnalyzer(){
230236
# -- END TEMP --
231237

232238
echo "Checking if Python dependencies are installed..."
233-
pip install -r ./src/analyzer/requirements.txt
239+
pip3 install -r ./src/analyzer/requirements.txt
234240
echo ""
235241

236242
# Set the Paths for the gossip-metrics.json peerstore.json and output
@@ -249,20 +255,53 @@ LaunchAnalyzer(){
249255
# Run the Analyzer
250256
echo " Launching analyzer"
251257
echo ""
252-
python ./src/analyzer/armiarma-analyzer.py "$csv" "$peerstore" "$extrametrics" "$plots"
258+
python3 ./src/analyzer/armiarma-analyzer.py "$csv" "$peerstore" "$extrametrics" "$plots"
253259

254260
# Deactivate the VENV
255261
deactivate
256262

257263
}
258264

265+
# Launch the General Overview of all the projects in the examples folder
266+
LaunchGeneralResults(){
267+
if [[ -d "./general-results/plots" ]]; then
268+
echo ""
269+
else
270+
mkdir "./general-results/plots"
271+
fi
272+
273+
# Source the virtual env
274+
source "${VENV}/bin/activate"
275+
276+
# Check if the virtual env is created
277+
venvPath="${PWD}/src/analyzer/venv"
278+
if [[ "$VIRTUAL_ENV" = "$venvPath" ]]
279+
then
280+
echo "VENV successfuly sourced"
281+
else
282+
echo "ERROR. VENV was unable to source" >&2
283+
fi
284+
echo ""
285+
286+
# Run the Analyzer
287+
echo " Launching General Overview Analyzer"
288+
echo ""
289+
python3 ./src/analyzer/total-overview-analysis.py ./examples ./general-results
290+
echo "results available in \$ARMIARMA/results"
291+
echo ""
292+
# Deactivate the VENV
293+
deactivate
294+
}
295+
296+
259297
# -------- END OF FUNCTION DEFINITION ---------
260298

261299
# Execution Secuence
262300

263301
# 0. Get the options
264302
go version
265303

304+
# Generate the examples folder
266305
if [[ -d ./examples ]]; then
267306
echo ""
268307
echo " ----------- ARMIARMA $version -----------"
@@ -274,6 +313,15 @@ else
274313
echo ""
275314
mkdir ./examples
276315
fi
316+
# Generate the general-results folder
317+
if [[ -d ./general-results ]]; then
318+
echo ""
319+
else
320+
echo ""
321+
echo "Generating ./general-results folder"
322+
echo ""
323+
mkdir ./general-results
324+
fi
277325

278326
# Check if any argument was given.
279327
# If not, print Help and exit
@@ -283,7 +331,7 @@ if [[ -z "$1" ]]; then
283331
exit 1
284332
fi
285333

286-
while getopts ":hcpfdts" option; do
334+
while getopts ":hcpfdo" option; do
287335
case $option in
288336
h) # display Help
289337
Help
@@ -329,10 +377,18 @@ while getopts ":hcpfdts" option; do
329377

330378
echo "Calling the Analyzer"
331379
LaunchAnalyzer "$folderName" "$folderPath"
332-
380+
333381
echo "Exit Crawler execution"
334382
exit;;
335383

384+
o) # Generate the general overview of the previously generated projects
385+
386+
LaunchGeneralResults
387+
388+
echo "Overview Analyzer Finished!"
389+
echo ""
390+
exit;;
391+
336392
d) # Option to run Armiarma Crawler for a specific given time on the iexec decentralice platform
337393
# processing the results with the Analyzer and returning the metrics and plots in a zip file
338394
# TODO: encrypt the results with a certain security measure, so noone can access to them

src/analyzer/armiarma-analyzer.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ def main():
752752

753753
## -- website code --
754754
print("\n")
755-
print("Results from crawler run on [month] running for [crawling time].<br>Total amount of peers on the peerstore:", peerstoreLen,".<br>Number of clients with the TPC port at 13000 (Prysm?):", cnt13000,".<br>Percentage of 'Prysm' peers from the peerstore (based on the TCP port):", round((cnt13000*100)/peerstoreLen,2),"%.<br>We manage to connect with", succeed,"peers from the peerstore.<br>This would be the distribution.")
755+
print("Results from crawler run on [month] running for [crawling time].\n<br>Total amount of peers on the peerstore:", peerstoreLen,".\n<br>Number of clients with the TPC port at 13000 (Prysm?):", cnt13000,".\n<br>Percentage of 'Prysm' peers from the peerstore (based on the TCP port):", round((cnt13000*100)/peerstoreLen,2),"%.\n<br>We manage to connect with", succeed,"peers from the peerstore.\n<br>This would be the distribution.")
756756
print("\n")
757757

758758

@@ -818,15 +818,15 @@ def main():
818818
'textSize': textSize+2,
819819
'yLowLimit': None,
820820
'yUpperLimit': None,
821-
'title': "Distribution of the detected errors",
822-
'xlabel': 'Number of peers',
821+
'title': "Distribution of the Experienced Connection Errors",
822+
'xlabel': 'Peers With Same Connection Error',
823823
'ylabel': None,
824824
'yticks': None,
825825
'vGrids': True,
826826
'titleSize': titleSize+2,
827827
'labelSize': labelSize+2,
828828
'legendPosition': 1,
829-
'legendTitle': 'Experienced errors',
829+
'legendTitle': 'Recorded errors',
830830
'legendSize': labelSize-4,
831831
'xticksSize': ticksSize,
832832
'yticksSize': ticksSize+2,
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# This file compiles the code to analyze the gathered metrics from each of the
2+
# folders in the $ARMIARMAPATH/examples folder, providing a global overview of the
3+
# Peer distributions and client types over the dayly analysis
4+
5+
import os, sys
6+
import json
7+
import pandas as pd
8+
import matplotlib.pyplot as plt
9+
import numpy as np
10+
11+
12+
def mainexecution():
13+
projectsFolder = sys.argv[1]
14+
outFolder = sys.argv[2]
15+
16+
outJson = outFolder + '/' + 'client-distribution.json'
17+
# So far, the generated panda will just contain the client count
18+
p = {'date': [], 'Lighthouse': [], 'Teku': [], 'Nimbus': [], 'Prysm': [], 'Lodestar': [], 'Unknown': []}
19+
# Concatenation of the Json values
20+
j = []
21+
print(projectsFolder)
22+
for root, dirs, _ in os.walk(projectsFolder):
23+
print(dirs)
24+
dirs.sort()
25+
# We just need to access the folders inside examples
26+
for d in dirs:
27+
fold = os.path.join(root, d)
28+
f = fold + '/metrics/custom-metrics.json'
29+
if os.path.exists(f):
30+
# Load the readed values from the json into the panda
31+
poblatePandaCustomMetrics(p, j, f)
32+
break
33+
34+
# Export the Concatenated json to the given folder
35+
with open(outJson, 'w', encoding='utf-8') as f:
36+
json.dump(j, f, ensure_ascii=False, indent=4)
37+
38+
# After filling the dict with all the info from the JSONs, generate the panda
39+
df = pd.DataFrame (p, columns = ['date', 'Lighthouse', 'Teku', 'Nimbus', 'Prysm', 'Lodestar', 'Unknown'])
40+
df = df.sort_values(by="date")
41+
print(df)
42+
43+
outputFigsFolder = outFolder + '/' + 'plots'
44+
clientList = ['Lighthouse', 'Teku', 'Nimbus', 'Prysm', 'Lodestar', 'Unknown']
45+
figSize = (10,6)
46+
titleSize = 24
47+
textSize = 20
48+
labelSize = 20
49+
# Plot the images
50+
plotStackedChart(df, opts={
51+
'figSize': figSize,
52+
'figTitle': 'Client-Distribution.png',
53+
'figtitle': 'client-distribution.png',
54+
'outputPath': outputFigsFolder,
55+
'align': 'center',
56+
'grid': 'y',
57+
'textSize': textSize,
58+
'title': "Evolution of the projected client distribution",
59+
'ylabel': 'Client concentration (%)',
60+
'xlabel': None,
61+
'yticks': np.arange(0, 110, 10),
62+
'legendLabels': clientList,
63+
'titleSize': titleSize,
64+
'labelSize': labelSize,
65+
'lengendPosition': 1,
66+
'legendSize': labelSize,
67+
'tickRotation': 90,
68+
'show': True})
69+
70+
def poblatePandaCustomMetrics(p, j, jsonFile):
71+
# Read the Json
72+
jsf = open(jsonFile)
73+
jsonValues = json.load(jsf)
74+
jsf.close()
75+
76+
# Add readed Json to the previous ones (concatenate them)
77+
j.append(jsonValues)
78+
79+
# Compose the date of the crawling day
80+
cday = str(jsonValues['StartTime']['Year']) + '-' + str(jsonValues['StartTime']['Month']) + '-' + str(jsonValues['StartTime']['Day'])
81+
p['date'].append(cday)
82+
ps = jsonValues['PeerStore']['Total']
83+
# Get percentages for each of the clients
84+
crwlig = jsonValues['PeerStore']['ConnectionSucceed']['Lighthouse']['Total']
85+
crwtek = jsonValues['PeerStore']['ConnectionSucceed']['Teku']['Total']
86+
crwnim = jsonValues['PeerStore']['ConnectionSucceed']['Nimbus']['Total']
87+
crwlod = jsonValues['PeerStore']['ConnectionSucceed']['Lodestar']['Total']
88+
crwunk = jsonValues['PeerStore']['ConnectionSucceed']['Unknown']['Total']
89+
90+
prysPort = jsonValues['PeerStore']['Port13000']
91+
res = ps - prysPort
92+
93+
noPrysm = crwlig + crwtek + crwnim + crwlod + crwunk
94+
95+
estimlig = (res*crwlig)/noPrysm
96+
estimtek = (res*crwtek)/noPrysm
97+
estimnim = (res*crwnim)/noPrysm
98+
estimlod = (res*crwlod)/noPrysm
99+
estimunk = (res*crwunk)/noPrysm
100+
101+
lig = round((estimlig*100)/ps, 2)
102+
tek = round((estimtek*100)/ps, 2)
103+
nim = round((estimnim*100)/ps, 2)
104+
pry = round((prysPort*100)/ps, 2)
105+
lod = round((estimlod*100)/ps, 2)
106+
unk = round((estimunk*100)/ps, 2)
107+
108+
p['Lighthouse'].append(lig)
109+
p['Teku'].append(tek)
110+
p['Nimbus'].append(nim)
111+
p['Prysm'].append(pry)
112+
p['Lodestar'].append(lod)
113+
p['Unknown'].append(unk)
114+
115+
116+
def plotStackedChart(p, opts):
117+
outputFile = str(opts['outputPath']) + '/' + opts['figTitle']
118+
119+
ax = p.plot.area(figsize = opts['figSize'], x='date', stacked=True)
120+
121+
# labels
122+
if opts['ylabel'] is not None:
123+
plt.ylabel(opts['ylabel'], fontsize=opts['labelSize'])
124+
if opts['xlabel'] is not None:
125+
plt.xlabel(opts['xlabel'], fontsize=opts['labelSize'])
126+
127+
handles,legends = ax.get_legend_handles_labels()
128+
ax.legend(handles=handles, labels=opts['legendLabels'], loc='upper center', bbox_to_anchor=(0.5, -0.05), fancybox=True, shadow=True, ncol=6)
129+
130+
if opts['grid'] != None:
131+
ax.grid(which='major', axis=opts['grid'], linestyle='--')
132+
133+
plt.yticks(opts['yticks'])
134+
135+
plt.title(opts['title'], fontsize = opts['titleSize'])
136+
plt.tight_layout()
137+
plt.savefig(outputFile)
138+
if opts['show'] is True:
139+
plt.show()
140+
141+
if __name__ == '__main__':
142+
mainexecution()

0 commit comments

Comments
 (0)