How can I track concurrent active users?

My employer wants to track the number of concurrent users to see if we have too many licences .

What is the best way to do that?

Any suggestions would help.



1 Like

I know there is a built in dashboard that shows user sessions. May be worth a look at.

There is also User Tracker, i’m more curious as to what tables on the database side could should concurrent users for multi sessions.

1 Like



Nice, So simple. I was only thinking about the user tables.

@tfenwick11, @aidacra,

Do any of you happen to know if licensing is by user or session?
If I have a user who is active in 5 companies, is that 5 licenses being used or 1?

If it is all from one workstation from one client instance and the session monitor is in use(it is automatically), that would be five technical sessions with one license being consumed.

1 Like


I looked at sessionstate and couldn’t glean much info from it.

What I need to do is see if I can create a list of unique users who currently have an active session going on.

I can then export that info a set intervals and create a report of peak users.

I looked at the dashboard that shows the currently active users. Unfortunately it doesn’t show how it got that info.

Any idea on how to create a BAQ to get what I need?

This data wasn’t intended to be consumed via BAQ/direct SQL query. The “best” solution would be to determine the BO and method that the EAC calls when it calls/retrieves the session information and call that via REST (or some other method) to get the data and do with it at that point what you wish to do.

That being said, the userid, licenseexpirationtime,and expireson columns should be straight forward to know what they represent. I suspect you only have one license in your db, so installationid will always be the same and isn’t important then.

So, log into your training database with userABC and check the sessionstate record.

  • When it’s active, it will have a specific value in the state column.
  • Wait for it to “time out” and the state will have a different specific value.
  • When you use a normal office license, it will have a specific sessiontype value.
  • When you use an MES license, it will have a different specific sessiontype.
  • when you launch a different company from the main menu, it will generate a different sessionstate record with a different specific sessiontype value…

and so on and so forth.

One could piece this together enough so that it could be done via BAQ. If you aren’t familiar with REST, this is an excellent example as to why it would be beneficial to learn because it is so much easier to query this data that way then what I laid out above.

Good luck :face_with_monocle:



Where do I learn about REST?

I have no problem learning new things, just need a good resource.

Enjoy REST Overview Novel


First of all - the Admin Console has all this information.

-I was doing load testing so don’t laugh at the 45K licenses :wink:

A few things to add - @aidacra is correct on where session is stored - by default -
Session is only accurate in the app server memory - the db table is the default option backup for if an appserver falls over and recycles. You can also plug in other storage mechanisms (not released but discussed in previous beta programs so there is some items floating around the internet on it).

So if you want to do more troubleshooting, you can look at the trace logs.
trace://ice/fw/session is your friend. Enable that flag in your appserver.config and you will see all activity going on around Sessions.
In 10.2.100 we a new trace flag that trims down the noise on sessions to just show when a license is in use or not - not why but just the counts - trace://ice/fw/license

An example is below.
Look at the element names to understand which trace they output comes from - Session or License. License is a heck of a lot less noisy so start there if on a newer version.

The details this gives are the client IP, the user name and what machine they accessed the server from.

It tells you which type of license ‘Default User’ is being consumed.
It tells you how many have been consumed and how many you have installed (1 of 45000)

When you logout, you see the release of the license:

If you want to build your own integration to monitor users, many have done so calling against the AdminSession Object. If you want to go down that path I’ll be happy to answer those questions as well.


I had the same question and found REST to be a great solution. I created a spreadsheet in Google Apps and it has a function executing a REST call every 15 minutes against the Ice.BO.AdminSessionSvc. The spreadsheet created shows licenses consumed at the time the script was run for both shop and office users. The user types were derived from observation and I don’t know if they are the same in all installations. We have two companies hence the two different REST accounts.

Take a look at the below and good luck!

Here is the supporting code:

var ShopUserLic;
var OffUserLic;

function Process()

var d = new Date(); // for now

if(d.getHours()>=7 && d.getHours()<=17 && d.getDay()>=1 && d.getDay()<=5)
var EDRESTAccount=‘USERID’;
var JDRESTAccount=‘USERID’;

var EDLic=QueryLicenses(EDRESTAccount);
var JDLic=QueryLicenses(JDRESTAccount);

var sheet=SpreadsheetApp.getActiveSheet();
//var sheet = spreadsheet.getSheets()[0];
var range = sheet.getRange("A2:G2");
var values = [
  [ Utilities.formatDate(new Date(), "GMT-5", "MM/dd/yyyy HH:mm:ss"), EDLic[0],EDLic[1],EDLic[2],JDLic[0],JDLic[1],JDLic[2] ]



function QueryLicenses(RESTAccount) {
//Account information for looking up data in Epicor
var ShopUserType=‘00000003-b8eb-40c4-8897-248cb30c5d47’;
var OfficeUserType=‘00000003-b615-4300-957b-34956697f040’
var Result = new Array(3);
var headers = {
“Authorization” : "Basic " + Utilities.base64Encode(RESTAccount + ‘:’ + RESTPass)

var params = {

var url=‘SERVERURL/api/v1/Ice.BO.AdminSessionSvc/List?$select=LicenseType&$filter=Expired%20eq%20false’;

var response = UrlFetchApp.fetch(url, params);
var responsetext=response.getContentText();
obj = JSON.parse(responsetext);
for (i = 0; i < obj.value.length; i++) {
case ShopUserType:
case OfficeUserType:
case ‘00000003-c071-4fd8-900d-f58ee96bbcce’:
return Result;

return Result;



For what its worth. Here’s a short PowerShell routine I wrote that’s scheduled to run every 15 minutes.
It uses a REST call to acquire session information.

#Bypass validation of self-signed certificate
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}

$uri = ‘https://servername/appservername/api/v1/Ice.BO.AdminSessionSvc/GetList
$creds = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(“username:password”))
$headers = @{ Authorization = "Basic "+$creds }
$body = ‘{“whereClause”:“Expired = false”, “pageSize”:0, “absolutePage”:0}’;

$resp = Invoke-RestMethod $uri -Headers $headers -Method Post -ContentType ‘application/json’ -Body $body

$lic = @{DataCollection=0; DefaultUser=0;}

foreach ($session in $resp.returnObj.AdminSessionList) {

$query = ‘INSERT INTO license_log (“DataCollection”,“DefaultUser”,interval) VALUES (’+

$conn = New-Object System.Data.Odbc.OdbcConnection(‘DSN=PGBI’)
$cmd = New-Object System.Data.Odbc.OdbcCommand($query,$conn)
$res = $cmd.ExecuteNonQuery()


For “normal” license use the session type is “DefaultUser”. When subsequent sessions are created for being active in another company the session type is “EnterpriseProcessing”, which doesn’t count against license use.