PHP - Log how many hours a user spent on the system - php

I'm trying to code (in an efficient way) a log to count how many hours a user spent on the system.
The only reliable information is the login date and time. User's often just close the window and don't log off.
What I've been doing so far is to use a jQuery call every 5 or 10 seconds to a specific endpoint to just record: user's id and the current datetime. But this is, of course, very expensive. A lot of HTTP requests (imagine for 8 hours a day how many requests) and a huge (HUGE) table.
Is there a more efficient way to count this information and present a summary of worked hours by the end of the month?
I'm currently using MySQL to log this (another table inside the same database) but I can use a different database if it's a better solution.

Related

Prevent Laravel Web-App / Webserver from getting overloaded

I have the following challenge... I created an appointment booking system with laravel 8, which allows people to book appointments which are then available in the admin area for the employees.
The webapp itself is running for a couple of months, but now I am getting more and more users, which lead already a couple of times to the situation, that the webserver / mysql was so overloaded that the website was not loading any more.
Analysis has shown, the too many queries are executed, as the calculation for open available time slots query the bookings table in the db, which got quite big over time (1.7gb table).
Surely I can optimize the db queries etc. but I still afraid, that too many concurrent web requests may lead to db/webserver blockage.
My question now is, what options would see to prevent this situation?
Apparently the main cause is the checkin of the available time slots function, which is executed every time the user selects a date in the dropdown (it will then execute an ajax call, which fetches the available time slots).
I was thinking about two possible solutions:
Queueing: would it make sense, to execute this ajax call as a Queued Job, so that not too many requests can block the db?
replace the ajax call for getting the timeslot with an internal api request? Hence instead of directly asking the db, I would as my backend API to get the time slots, which then may throttle the requests if there are too many?
Or are there better options???
I hope you could explain the issue and my desired target.
Thank you very much in advance!

Building a live database (approach)

I just want a approach on how to build a database with live records, so don't just downvote. I don't expect any code.
At the moment I have a MySql database with about 2 thousand users, they are are getting more though. Each player/user has several points, which are increasing or decreasing by certain actions.
My goal is that this database gets refreshed about every second and the user with more points move up and others move down... and so on
My question is, what is the best approach for this "live database" where records have to be updated every second. In MySql I can run time based actions which are executing a SQL command but this isn't the greatest way I think. Can someone suggest a good way to handle this? E.g. other Database providers like MongoDB or anything else?
EDIT
This doesn't work client side, so I can't simply push/post it into the databse due some time based events. For explanation: A user is training his character in the application. This training (to get 1 level up) takes 12 hours. After the time is elapsed the record should be updated in the database AUTOMATICALLY also if the user doesn't send a post request by his self (if the user is not logged in) other users should see the updated data in his profile.
You need to accept the fact that rankings will be stale to some extent. Your predicament is no different than any other gaming platform (or SO rankings for that matter). Business decisions were put in place and constantly get reviewed for the level of staleness. Take the leaderboards on tags here, for instance. Or the recent change that has profile pages updated a lot more frequently, versus around 4AM GMT.
Consider the use of MySQL Events. It is built-in functionality that replaces the need for cron tasks. I have 3 event-related links off my profile page if interested. You could calculate ranks on a timed schedule (your tolerance for staleness) and the users' requests for them would be fast (faster than the below from Gordon). On the con-side, they are stale.
Consider not saving (writing) rank info but rather focus just on filling in the slots of your other data. And get your rankings on the fly. As an example, see this rankings answer here from Gordon. It is dynamic, runs upon request with at least at that moment non-staleness, and would not require Events.
Know that only you should decide what is tolerable for the UX.

Currently online visitors logic in PHP

It could be a really easy thing to do but I am getting pretty confused by it.
Basicly, I want to get the amount of people currently browsing my website. The problem is, I can't count sessions. Many of them are created for different purposes. (e.g $_SESSION['age'] for the users who logged in.)
Also, there are "logged_in" and "not_logged_in" people.
In short, how can I count the users in my website in the most professional way?
Ps. Please note that I will run the function every 1-5 minutes, get the amount, store it to be used as cache. After 5 minutes, cache will be replaced again, and so on. Hence, db connections will be a possibility if you think that would be the most professional way.
One of the issues at hand is, your PHP doesn't know when your user closes the browser.
I've done something similar with a combination of a "last_used"-field in the user database (timestamp/datetime) and a "heartbeat"-function (jscript), which regularly sends an "I'm still alive"-command to the server (every x seconds), where then this last_used-field is updated. It ain't a high traffic site, but it does the job very reliable.
Then just count the amount of users which a very current heartbeat in the database:
SELECT COUNT(*)
FROM your_user_table
WHERE last_used > TIMESTAMPADD(NOW(), INTERVAL -30 SECOND)
You don't need a user table for this, you can use a session table, too. Such a mechanism can then be used for other features, too, like giving the users new messages on the fly and similar.

limiting access to a report

I'm doing a report using PHP and SQL SERVER 2000
In this report, PHP page is accessing a live database with lot of
processes happening.
The problem i'm facing is, when i give this report to users they
frequently access the report and it can cause havoc to the daily
processes.
I want to limit the access time for a given day to some number(let's
say 10 times per day) or between two hours periods per person(once accessed a person only can view the report after 2
hours).
Is this achievable via PHP? or do i need to do it in SQL SERVER 2000
configurations?
Please provide me with a detailed answer with the references if
possible
You quite simply enable/create caching, so the report is generated a few times a day (either a cronjob / time generation) or by user activation, then allow that report to 'live' for a few hours (or whatever your parameters are).
Basically you need to create some caching PHP side. I would create a copy of the report then send that to users, and update it throughout the day without their interaction.
UPDATE
A quick example I found: http://www.devshed.com/c/a/PHP/Output-Caching-with-PHP/

PHP, how do I calculate total online time of a user?

What is the best way to calculate the total time spent by a registered user on the site? ...under these conditions
1) User logs out normally.
2) User can simply close browser.
3) User can auto-login next time he comes back.
I think the best way to do this would be to find the time spent by the user on each page and keep adding them to his total time instead of checking for the whole site. But I don't know how to implement that....please help
You can't find the exact time he leaves the system, unless he logs out. Even then, he might be browsing the site while logged out.
The approximate way to do this would be to set the start time in the session and keep incrementing the time everytime he visits a page.
So the first time the user comes to your site at time T, you will
Create a session and put the start time there
Add the total time as 0
For all subsequent requests you would
Check the start time and compare that with the time now and get the difference
Add that time to the total time
This method will not give you the time the user spent on the last page. But it will give you something to work with.
You can do this with JavaScript and a separate PHP script.
The javascript code reacts to events that mean that an user is active (such as mouse/keyboard/resize events) and invokes the php script.
The php script compares the time when it last received a request to the current time and checks if the difference is over a certain threshold (i suggest something like 10-30 minutes to prevent single-click sessions from adding up) nothing happens.
If the threshold is not reached then the difference between the two timestamps is added to the total sum in the database.
Afterwards (in both cases) the last request time is set to the current time and the script ends.
If you also want to know when the user closes your website pages you can subscribe to unload events and/or implement an heartbeat script that calls a PHP script every X seconds.
you have 2 approaches, either to create a log table in your DB to track each user (by ID) logins and logouts and then calculate the time difference between the two in each record for the specific user and then sum all of that. OR you go more complex and make 4 columns in your DB->usertable (logintime 'timestamp' - logouttime 'timestamp' - lastactive 'timestamp' - onlinetime 'int') and update each column as their names say by code according to user activities. then alter the Session.php script in the System/libraries directory at line 105 exactly after if ( ! $this->sess_read()) before the system creates a new session and write a code to check if the 'logouttime' is not the same as 'lastactive' time (to avoid session timeout expiry misunderstood in the next code) if both fields not the same, update your DB to make 'logouttime' equals 'lastactive' then at line 107 exactly after: $this->sess_update(); write a code to check if the 'logouttime' equals the 'lastactive' (and you will make that happen earlier in your logout.php script) write a code to calculate the online time by the difference between the 'logintime' and the now time 'time()' and add the result to the 'onlinetime' field. but if the 'logoutime' is not the same as 'lastactive' (that meanse the user is online and making activities in your site because you are tracking him and updating the 'lastactive' field frequently) then write a code to calculate the online time by the difference between the 'lastactive' and now time 'time()' and add the result to the 'onlinetime' field. that way you have the exactly online time logged forever in the 'onlinetime' field! I hope you got me right because the examples will be a lot long of scripts (although I don't mind to share upon request). good luck.
Use the Session ID to keep track of individual sessions.

Categories