Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to monitor bandwidth consumption of a user in PHP

Ok I know this is a weird problem and may not be possible, so ideas would be appreciated.

Anyways, I want to find out how much bandwidth I am giving to each user. I identify a user when he logins to the website.

So basically for every request, I want to know how much bandwidth was used by that request. And if a user was logged in at that time, I will add the amount to his account.

Will be using codeigniter, though I doubt that makes a difference.

Everything will be on the same Linux based server with Apache, for now at least.

Ideally I'd like a solution that's not limited to the type of hosting.

Will be using either Google cloud or amazon AWS. If the solution is limited to google cloud or aws, it will work.

like image 270
Ahmed-Anas Avatar asked Jan 01 '16 10:01

Ahmed-Anas


People also ask

How do I monitor Internet bandwidth usage of each user?

One way to assess a network's bandwidth usage is to run a network internet speed test. This allows you to view your network download and upload speeds in near real time. Running a test like this during several points in the day can give a general idea of overall usage and help with measuring bandwidth usage trends.


1 Answers

Since you said you are on Apache, here are 2 ideas.

First idea (the so-so idea but fun to think about...):

Cookies are sent with every request on the server (including to all images etc). When the user logs in set a cookie with PHP and name it USERTOKEN then set the value of it to an md5+salt of that user's id.

Insert %{USERTOKEN}C and %B into a custom LogFormat directive.

%{Foobar}C  The contents of cookie Foobar in the request sent to the server. 
            Only version 0 cookies are fully supported.

%B          Size of response in bytes, excluding HTTP headers.

Now, you create a custom log format that looks like this:

LogFormat "%B %{USERTOKEN}C" php_bandwidth_log
CustomLog "logs/php_bandwidth_log" php_bandwidth_log

Then, you create a script to to parse the php_bandwidth_log and map it to the original user's id.

Unfortunately this idea isn't foolproof since someone could still hypothetically access site content by not passing a cookie (maybe). Anyway, depending on your situation this may work for you, if not, an alternative and better idea is to basically route all the content through PHP script so you can do any kind of logging you want on it.

Second idea (better):

So, create a PHP file that can be called like this /files.php?path=/blah/blah.jpg (oversimplified for this example, could be prettied up with a mod_rewrite rule) then inside of it you you can log that user's id and track the files accessed. This is assuming you only want to track files. This wouldn't be keeping track of the HTML that is generated on the page - you could probably use the custom Apache logging idea mentioned earlier but modify it a little bit to get that information.

Here is some pseudo code to help you get the idea:

if (!$hasSession) {
    die("Invalid session");
}
$size = filesize($path);
insert_into_bandwidth_table($userId, $size);
header("Content-Type: ...");
readfile($path);

The following is how you can track just the response size for the executed PHP scripts BUT it will only work if you are running PHP as a module.

In your PHP add something like this. Basically this allows Apache to read this variable for log writing purposes:

apache_note("PHP_USER_ID", 1234);

apache_note — apache_note — Get and set apache request notes

Description: This function is a wrapper for Apache's table_get and table_set. It edits the table of notes that exists during a request. The table's purpose is to allow Apache modules to communicate.

Read more here

Then in your httpd.conf log configuration do something like this:

LogFormat "%B %{PHP_USER_ID}n" php_bandwidth_log
CustomLog "logs/php_bandwidth_log" php_bandwidth_log

Info on the note from docs:

%{Foobar}n  The contents of note Foobar from another module.

And... just realized there is an alternative to apache_note in case you are not running it as a module. Your PHP code would instead do this:

apache_setenv('PHP_USER_ID', $userId, TRUE);

Then to log you would use this LogFormat directive:

LogFormat "%B %{PHP_USER_ID}e" php_bandwidth_log
like image 66
Clay Avatar answered Oct 26 '22 00:10

Clay