Skip to content

Commit 640045b

Browse files
authored
Move the rest-traffic logic inside waku-simulator (#103)
* Move the rest-traffic logic inside waku-simulator to be built locally * Enable timestamp for rest-traffic
1 parent 00bc66f commit 640045b

File tree

5 files changed

+127
-1
lines changed

5 files changed

+127
-1
lines changed

docker-compose.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ services:
9999
- simulation
100100

101101
rest-traffic:
102-
image: alrevuelta/rest-traffic:28430f8
102+
build:
103+
context: ./tools/rest-traffic
104+
dockerfile: Dockerfile
103105
command:
104106
--multiple-nodes=http://waku-simulator-nwaku-[1..${NUM_NWAKU_NODES:-5}]:8645
105107
--msg-size-kbytes=${MSG_SIZE_KBYTES:-10}

tools/rest-traffic/Dockerfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FROM python:3.9-slim
2+
3+
WORKDIR /app
4+
5+
COPY requirements.txt requirements.txt
6+
7+
RUN pip install --no-cache-dir -r requirements.txt
8+
9+
COPY . .
10+
11+
ENTRYPOINT ["python", "./traffic.py"]

tools/rest-traffic/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# rest-traffic
2+
3+
Test utility for [nwaku](https://github.com/waku-org/nwaku).
4+
Given the REST API endpoint, it injects traffic with a given message size at a given rate.
5+
6+
See usage:
7+
```
8+
./python traffic.py ---help
9+
```
10+
11+
Use with docker:
12+
```
13+
build:
14+
context: ./tools/rest-traffic
15+
dockerfile: Dockerfile
16+
```
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
requests==2.32.3
2+
argparse==1.4.0

tools/rest-traffic/traffic.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import requests
2+
import time
3+
import datetime
4+
import os
5+
import base64
6+
import urllib.parse
7+
import requests
8+
import argparse
9+
import re
10+
11+
def send_waku_msg(node_address, kbytes, pubsub_topic, content_topic):
12+
# TODO dirty trick .replace("=", "")
13+
base64_payload = (base64.b64encode(os.urandom(kbytes*1000)).decode('ascii')).replace("=", "")
14+
print("size message kBytes", len(base64_payload) *(3/4)/1000, "KBytes")
15+
body = {
16+
"payload": base64_payload,
17+
"contentTopic": content_topic,
18+
"version": 1, # You can adjust the version as needed
19+
"timestamp": int(time.time())
20+
}
21+
22+
encoded_pubsub_topic = urllib.parse.quote(pubsub_topic, safe='')
23+
24+
url = f"{node_address}/relay/v1/messages/{encoded_pubsub_topic}"
25+
headers = {'content-type': 'application/json'}
26+
27+
readable_time = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
28+
print('[%s] Waku REST API: %s PubSubTopic: %s, ContentTopic: %s' % (readable_time, url, pubsub_topic, content_topic))
29+
s_time = time.time()
30+
31+
response = None
32+
readable_time = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
33+
try:
34+
print('[%s] Sending request' % readable_time)
35+
response = requests.post(url, json=body, headers=headers)
36+
except Exception as e:
37+
print(f"Error sending request: {e}")
38+
39+
if(response != None):
40+
elapsed_ms = (time.time() - s_time) * 1000
41+
readable_time = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
42+
print('[%s] Response from %s: status:%s content:%s [%.4f ms.]' % (readable_time, node_address, \
43+
response.status_code, response.text, elapsed_ms))
44+
45+
parser = argparse.ArgumentParser(description='')
46+
47+
# these flags are mutually exclusive, one or the other, never at once
48+
group = parser.add_mutually_exclusive_group(required=True)
49+
group.add_argument('-sn', '--single-node', type=str, help='example: http://waku-simulator-nwaku-1:8645')
50+
group.add_argument('-mn', '--multiple-nodes', type=str, help='example: http://waku-simulator-nwaku-[1..10]:8645')
51+
52+
# rest of araguments
53+
parser.add_argument('-c', '--content-topic', type=str, help='content topic', default="my-ctopic")
54+
parser.add_argument('-p', '--pubsub-topic', type=str, help='pubsub topic', default="/waku/2/rs/66/0")
55+
parser.add_argument('-s', '--msg-size-kbytes', type=int, help='message size in kBytes', default=10)
56+
parser.add_argument('-d', '--delay-seconds', type=int, help='delay in second between messages', required=15)
57+
args = parser.parse_args()
58+
59+
print(args)
60+
61+
if args.single_node != None:
62+
print("Injecting traffic to single node REST API:", args.single_node)
63+
64+
# this simply converts from http://url_[1..5]:port to
65+
# [http://url_1:port or from http://url-[1..5]:port to
66+
# [http://url-1:port
67+
nodes = []
68+
if args.multiple_nodes:
69+
start, end = (int(x) for x in re.search(r"\[(\d+)\.\.(\d+)\]", args.multiple_nodes).groups())
70+
71+
if start is None or end is None:
72+
print("Could not parse range of multiple_nodes argument")
73+
exit
74+
75+
print("Injecting traffic to multiple nodes REST APIs")
76+
for i in range(end, start - 1, -1):
77+
nodes.append(re.sub(r"\[\d+\.\.\d+\]", str(i), args.multiple_nodes))
78+
79+
for node in nodes:
80+
print(node)
81+
82+
while True:
83+
# calls are blocking
84+
# limited by the time it takes the REST API to reply
85+
86+
if args.single_node != None:
87+
send_waku_msg(args.single_node, args.msg_size_kbytes, args.pubsub_topic, args.content_topic)
88+
89+
if args.multiple_nodes != None:
90+
for node in nodes:
91+
send_waku_msg(node, args.msg_size_kbytes, args.pubsub_topic, args.content_topic)
92+
93+
readable_time = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
94+
print('[%s] sleeping: %s seconds' % (readable_time, args.delay_seconds))
95+
time.sleep(args.delay_seconds)

0 commit comments

Comments
 (0)