For session duration you can look at _Connect._connect-time ("Login time"). It is a character value that looks like this: "Thu Dec 1 18:05:24 2016". but with a bit of code you can turn that into a datetime and subtract it from NOW to get the database session connection time in milliseconds. If you have a business rule that says all interactive self-service users should be logged out within x minutes after a certain end-of-business time, and you only want to know about time between database accesses, then this approach will work.
But this approach won't tell you what connected users are doing, e.g. if they're using the UI. You can sample _UserIO to see if their DB I/O changes between samples, but again that will give false positives for active users who aren't hitting the database. As suggested in
this article you could enable client statement caching and look at changes in the users' call stacks (only in 10.1C+), but I wouldn't do that. First, it's a bit risky to leave it enabled all the time, especially if you use "stack" instead of "single". Second, it's a performance hit. Third, the clients only send their call stack to the server when they do database I/O, so it would be updated at the same time as _UserIO.
I suspect that trying to get more info from the client on what it's doing, even between database accesses, would require changing its UI/business logic. In that case the solution might be more invasive than the problem.