# Monitoring or Logs for Bandwidth Usage Per User

**URL:** <https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468>\
**Category:** Pritunl VPN\
**Tags:** pritunl\
**Created:** [October 19, 2022, 8:26am UTC](https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468 "2022-10-19T08:26:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![JesusIslam](https://forum.pritunl.com/user_avatar/forum.pritunl.com/jesusislam/32/187_2.png) [@JesusIslam](https://forum.pritunl.com/u/JesusIslam)\
**Post date:** [October 19, 2022, 8:26am UTC](https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468/1 "2022-10-19T08:26:56Z")

</div>

Is there even such a thing? I know we have one on server level, but I need it per user level. Is there some resources or examples I could read if I would like to make a PR for this or is there any other consideration for not including this feature? Thank you.

---

<div class="post-metadata">

**Author:** ![zach](https://forum.pritunl.com/user_avatar/forum.pritunl.com/zach/32/1105_2.png) [@zach](https://forum.pritunl.com/u/zach)\
**Post date:** [October 19, 2022, 6:59pm UTC](https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468/2 "2022-10-19T18:59:59Z")

</div>

Pritunl doesn’t log bandwidth usage.

---

<div class="post-metadata">

**Author:** ![matholleville](https://forum.pritunl.com/user_avatar/forum.pritunl.com/matholleville/32/302_2.png) [@matholleville](https://forum.pritunl.com/u/matholleville)\
**Post date:** [November 27, 2024, 11:08pm UTC](https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468/3 "2024-11-27T23:08:27Z")

</div>

Is it planned to add this feature? We have an enterprise license, and this feature is essential to understand and monitor whether a user is consuming bandwidth excessively.

---

<div class="post-metadata">

**Author:** ![zach](https://forum.pritunl.com/user_avatar/forum.pritunl.com/zach/32/1105_2.png) [@zach](https://forum.pritunl.com/u/zach)\
**Post date:** [November 29, 2024, 10:44am UTC](https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468/4 "2024-11-29T10:44:55Z")

</div>

This data is sent to InfluxDB if that is configured.

The handler `user_bandwidth` has been added to also send this data to the [**plugin system**](https://docs.pritunl.com/docs/plugins). This is called every 15 seconds with the users bandwidth for that period. The rate can be adjusted with `sudo pritunl set vpn.bandwidth_update_rate 15`. The new plugin handler won’t be available until the next release.

---

<div class="post-metadata">

**Author:** ![MountainDancer](https://forum.pritunl.com/user_avatar/forum.pritunl.com/mountaindancer/32/1553_2.png) [@MountainDancer](https://forum.pritunl.com/u/MountainDancer)\
**Post date:** [September 11, 2026, 10:40am UTC](https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468/5 "2026-09-11T10:40:33Z")

</div>

If InfluxDB is not used, but we’d like to have logs written by the plugin system, can we increase the interval to for example, 1 hour, or is there a limit above which the bandwidth is not properly tracked anymore?

---

<div class="post-metadata">

**Author:** ![zach](https://forum.pritunl.com/user_avatar/forum.pritunl.com/zach/32/1105_2.png) [@zach](https://forum.pritunl.com/u/zach)\
**Post date:** [September 11, 2026, 12:15pm UTC](https://forum.pritunl.com/t/monitoring-or-logs-for-bandwidth-usage-per-user/468/6 "2026-09-11T12:15:55Z")

</div>

It shouldn’t be increased past 60 seconds. The hour interval should instead be handled by the plugin, below is an example on how this can be done.

```python
from pritunl import logger

import threading

_lock = threading.Lock()
_period_start = None
_period_totals = {}

def _flush_period(period_start, period_totals):
    for totals in period_totals.values():
        logger.info('User bandwidth hourly', 'plugin',
            period_start=period_start,
            host_id=totals['host_id'],
            host_name=totals['host_name'],
            server_id=totals['server_id'],
            server_name=totals['server_name'],
            org_id=totals['org_id'],
            org_name=totals['org_name'],
            user_id=totals['user_id'],
            user_name=totals['user_name'],
            device_id=totals['device_id'],
            device_name=totals['device_name'],
            remote_ip=totals['remote_ip'],
            virtual_ip=totals['virtual_ip'],
            virtual_ip6=totals['virtual_ip6'],
            bytes_sent=totals['bytes_sent'],
            bytes_recv=totals['bytes_recv'],
            samples=totals['samples'],
        )

def user_bandwidth(host_id, server_id, org_id, user_id, device_id,
        host_name, server_name, org_name, user_name, device_name,
        remote_ip, virtual_ip, virtual_ip6, timestamp,
        bytes_sent, bytes_recv, **kwargs):
    global _period_start
    global _period_totals

    period_start = timestamp.replace(minute=0, second=0, microsecond=0)
    key = (server_id, org_id, user_id, device_id)
    flush_start = None
    flush_totals = None

    with _lock:
        if _period_start is None:
            _period_start = period_start
        elif period_start > _period_start:
            flush_start = _period_start
            flush_totals = _period_totals
            _period_start = period_start
            _period_totals = {}
        elif period_start < _period_start:
            period_start = _period_start

        totals = _period_totals.get(key)
        if totals is None:
            totals = {
                'host_id': host_id,
                'host_name': host_name,
                'server_id': server_id,
                'server_name': server_name,
                'org_id': org_id,
                'org_name': org_name,
                'user_id': user_id,
                'user_name': user_name,
                'device_id': device_id,
                'device_name': device_name,
                'remote_ip': remote_ip,
                'virtual_ip': virtual_ip,
                'virtual_ip6': virtual_ip6,
                'bytes_sent': 0,
                'bytes_recv': 0,
                'samples': 0,
            }
            _period_totals[key] = totals
        else:
            totals['remote_ip'] = remote_ip
            totals['virtual_ip'] = virtual_ip
            totals['virtual_ip6'] = virtual_ip6

        totals['bytes_sent'] += bytes_sent or 0
        totals['bytes_recv'] += bytes_recv or 0
        totals['samples'] += 1

    if flush_totals:
        _flush_period(flush_start, flush_totals)

```
