In this document, $YOUR_IP
refers to your public ip address.
First, we must make a clear distinction between RPC traffic and P2P traffic. As a node operator you might think "wow my node is doing so much traffic WTF where are all these bytes coming from and going to". Well, this is actually due to your P2P port being exposed, which is port 18080
. This document does not cover the monitoring of P2P traffic. This document is specifically for the RPC port which runs on 18081
(or 18089
).
As Monero RPC traffic is HTTP, we can use nginx to reverse proxy and record bandwidth passing through. This implies that monerod's RPC port stays on localhost
Where normally we would use:
./monerod --max-concurrency 2 --rpc-bind-ip YOUR.IP.GOES.HERE --rpc-bind-port 18089 --restricted-rpc
We would now use:
./monerod --max-concurrency 2 --rpc-bind-port 18089 --restricted-rpc
And let it bind to localhost:
netstat -tulpn | grep 18089
tcp 0 0 127.0.0.1:18089 0.0.0.0:* LISTEN 11242/./monerod
So that we have some room on $YOURIP:18089
for nginx.
First install sudo apt install nginx nginx-extras
(ubuntu).
Edit /etc/nginx/nginx.conf
and add this code inside the http {
block:
log_format monerod_custom '<ip> [$time_iso8601] "$request" $status $bytes_sent $request_length';
Create a new server config /etc/nginx/sites-enabled/monerod.conf
server {
listen $YOURIP:18089;
more_clear_headers Server;
access_log /var/log/nginx/monerod.log monerod_custom;
error_log /var/log/nginx/monerod-err.log;
root /var/www/html;
index index.html;
location / {
allow all;
add_header Server Epee-based always;
proxy_hide_header Server;
proxy_pass http://127.0.0.1:18089;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
}
location ~ /\.ht {
deny all;
}
}
Now restart nginx: sudo systemctl restart nginx
And observe the custom log format in /var/log/nginx/monerod.log
.
To gather bandwidth statistics from the nginx logs, we can use the following hacky python3 script:
Edit: I repeat, a very hacky Python script. This is just for demonstration purposes
#/usr/bin/python3
import sys
import re
import gzip
from glob import glob
from datetime import datetime
print("Monero RPC bandwidth")
print("=================")
print()
NGINX_LOG_PATH = '/var/log/nginx/monerod.log'
DATE_FILTER = sys.argv[1]
DATE_FILTER = datetime.strptime(DATE_FILTER, '%Y-%m-%d')
def size_human(size, precision=2):
suffixes = ['B', 'KB', 'MB', 'GB', 'TB']
_index = 0
while size > 1024 and _index < 4:
_index += 1
size = size / 1024.0
return "%.*f%s" % (precision, size, suffixes[_index])
def read_nginx_log(fn, date_filter):
lines = []
_date_filter = date_filter.strftime('%Y-%m-%d')
if fn.endswith('.gz'):
with gzip.open(fn, 'rb') as f:
for line in f:
if not line:
continue
line = line.decode('utf8')
if _date_filter not in line:
continue
line = line.strip()
lines.append(line)
return lines
with open(fn, 'r') as f:
for line in f.readlines():
if not line or _date_filter not in line:
continue
lines.append(line.strip())
return lines
def parse_nginx_logs(date_filter):
global NGINX_LOG_PATH
data = []
for logfile in glob("%s*" % NGINX_LOG_PATH):
print('reading %s' % logfile)
lines = read_nginx_log(logfile, date_filter)
for line in lines:
date = re.findall(r'\[(.*)\]', line)
if not date:
continue
date = date[0]
try:
date = date[:date.find('+')]
# date = datetime.strptime(date.strip(), '%d/%b/%Y:%H:%M:%S')
date = datetime.strptime(date.strip(), '%Y-%m-%dT%H:%M:%S')
except Exception as ex:
continue
if ']' not in line:
continue
line = line[line.find(']')+2:]
bytes_sent, bytes_received = map(int, line.split(' ')[-2:])
data.append({
'date': date,
'bytes_sent': bytes_sent,
'bytes_received': bytes_received
})
return data
data = parse_nginx_logs(DATE_FILTER)
# sort on date
data = sorted(data, key=lambda k: k['date'], reverse=False)
min_date = data[0]['date']
max_date = data[-1]['date']
bytes_received = sum([z['bytes_received'] for z in data])
bytes_sent = sum([z['bytes_sent'] for z in data])
print()
print(min_date.strftime('%Y-%m-%d %H:%M:%S') + " <-> " + max_date.strftime('%Y-%m-%d %H:%M:%S'))
print("=================")
print("Bytes received: %s" % size_human(bytes_received))
print("Bytes sent: %s" % size_human(bytes_sent))
$ python3 rpc_bandwidth.py 2018-12-15
Where the first input is the date you want bandwidth of.
Monero RPC bandwidth
=================
reading /var/log/nginx/monerod.log
reading /var/log/nginx/monerod.log.2.gz
reading /var/log/nginx/monerod.log.1
2018-12-15 00:00:17 <-> 2018-12-15 19:21:59
=================
Bytes received: 14.54MB
Bytes sent: 8.74GB
author: dsc