Skip to content

Commit f0e61b4

Browse files
committed
fixed Failure errors, made output_file optional, and added new curl timers
1 parent 6d20f07 commit f0e61b4

File tree

1 file changed

+37
-23
lines changed

1 file changed

+37
-23
lines changed

tasks/measurements/alexa/alexa.py

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Dict, Union
22
from netunicorn.base import Task, Failure
3-
from pprint import pprint
43
import subprocess
4+
import pprint
55
from ping3 import ping
66
import csv
77
import json
@@ -13,7 +13,7 @@ class AlexaWebsitesTask(Task):
1313
"pip install ping3"
1414
]
1515

16-
def __init__(self, domain: str = None, filepath: str = None, output_path: str = None, top_k: int = 100, *args, **kwargs):
16+
def __init__(self, domain: str = None, filepath: str = "alexa_websites.csv", output_path: str = None, top_k: int = 100, *args, **kwargs):
1717
super().__init__(*args, **kwargs)
1818
self.domain = domain
1919
self.filepath = filepath
@@ -31,7 +31,7 @@ def measure_ping(self) -> Union[Dict[str, float], Failure]:
3131
try:
3232
ping_value = ping(self.domain)
3333
if ping_value is None:
34-
return Failure({"Ping returned None."})
34+
return Failure("Ping returned None.")
3535
return {"value": ping_value * 1000, "unit": "ms"}
3636
except Exception as e:
3737
return Failure(f"Ping failed: {e}")
@@ -46,20 +46,33 @@ def measure_dns_time(self) -> Union[Dict[str, float], Failure]:
4646
except Exception as e:
4747
return Failure(f"DNS resolution failed: {e}")
4848

49-
def measure_ttfb(self) -> Union[Dict[str, float], Failure]:
49+
def measure_timing(self) -> Union[Dict[str, Dict[str,float]], Failure]:
5050
try:
5151
result = subprocess.run([
5252
"curl",
5353
"-o", "/dev/null",
5454
"-s",
55-
"-w", "%{time_starttransfer}",
55+
"-w",
56+
(
57+
"time_appconnect: %{time_appconnect}\n"
58+
"time_connect: %{time_connect}\n"
59+
"time_namelookup: %{time_namelookup}\n"
60+
"time_pretransfer: %{time_pretransfer}\n"
61+
"time_redirect: %{time_redirect}\n"
62+
"time_starttransfer: %{time_starttransfer}\n"
63+
"time_total: %{time_total}\n"
64+
),
5665
"-H", "Cache-Control: no-cache",
57-
f"http://{self.domain}",
66+
f"https://{self.domain}",
5867
], capture_output=True, text=True, check=True)
59-
ttfb = float(result.stdout.strip()) * 1000 # s to ms
60-
return {"value": ttfb, "unit": "ms"}
68+
metrics = {
69+
key.strip(): {"value": float(value.strip()) * 1000, "unit": "ms"}
70+
for line in result.stdout.splitlines()
71+
for key, value in [line.split(": ", 1)]
72+
}
73+
return metrics
6174
except Exception as e:
62-
return Failure(f"TTFB measurement failed: {e}")
75+
return Failure(f"Network Timing measurement failed: {e}")
6376

6477
@staticmethod
6578
def load_websites(filepath: str, top_k: int) -> list:
@@ -78,16 +91,14 @@ def run(self) -> Union[Dict[str, Dict], Failure]:
7891
if self.domain:
7992
# Run for a single domain
8093
return {
81-
"domain": self.domain,
8294
"traceroute": self.get_traceroute(),
8395
"ping_time": self.measure_ping(),
8496
"dns_time": self.measure_dns_time(),
85-
"ttfb_time": self.measure_ttfb(),
97+
"measure_timing": self.measure_timing(),
8698
}
87-
88-
elif self.filepath and self.output_path:
89-
# Run for all websites in the file
90-
websites = AlexaWebsitesTask.load_websites(self.filepath, self.top_k)
99+
else:
100+
# Run for all websites in a file
101+
websites = self.load_websites(self.filepath, self.top_k)
91102
print(f"Loaded {len(websites)} websites.")
92103

93104
results = {}
@@ -99,12 +110,15 @@ def run(self) -> Union[Dict[str, Dict], Failure]:
99110
except Exception as e:
100111
results[website] = Failure(f"Failed to process {website}: {e}")
101112

102-
# Save results to a JSON file
103-
with open(self.output_path, "w") as f:
104-
json.dump(results, f, indent=4)
105-
106-
print(f"Results saved to {self.output_path}")
113+
# Save results to a JSON file if output_path is provided
114+
if self.output_path:
115+
print(f"Saving results to {self.output_path}")
116+
try:
117+
with open(self.output_path, "w") as f:
118+
json.dump(results, f, indent=4)
119+
except Exception as e:
120+
return Failure(f"Failed to write results to file: {e}")
121+
else:
122+
pprint.pp(results)
123+
107124
return results
108-
109-
else:
110-
raise Failure("Either a domain or both a filepath and output_path must be provided.")

0 commit comments

Comments
 (0)