Monitoring Concurrent Sessions in SAP BI Platform 4.0 and BusinessObjects Enterprise XI3.1
Some of you may already be familiar with the new licensing model available for SAP BusinessObjects BI, but for those who aren’t, let me take a couple of minutes to explain Concurrent Sessions (CS) licensing and how it works.
Historically the CPU license model has been used extensively and remains a popular way to bring BI to a large number of report consumers at a reasonable cost. CPU licensing allows an unlimited number of users to access the system. For minimally intensive usage such as viewing of previously scheduled reports, distribution of agnostic documents such as PDF/XLS, and Crystal Reports viewing and refreshing, it can enable a vast number of business users to run successfully on just a few CPU.
On the other hand, customers wishing to implement more interactive BI (and thus more CPU intensive!), in the form of Web Intelligence ad-hoc, Explorer, and Dashboards, could quickly find themselves needing dozens (or even hundreds) of CPU to service a smaller user population. This could make the CPU license model become cost prohibitive very quickly. Fortunately for us SAP has listened, and delivered a complimentary license model that allows us to purchase the necessary number of concurrent sessions and scale CPU as required without the corresponding license cost. For those of you that don’t already know, a concurrent session represents a connected user, in terms of InfoView/BI Launch Pad, Web Intelligence, Mobile, or any other client of the Business Intelligence system.
There is, however, some additional maintenance required to ensure exceeding your allotment of concurrent sessions does not interrupt business usage. Users could be prevented from logging onto the system, receiving an error message like the following:
All of your system’s ‘N’ Concurrent Access Licenses are in use at this time or your system’s license key has expired. Try again later or contact your administrator to obtain additional licenses.
BI4 Session Monitoring
Obviously we don’t want our preferred license model to have negative repurcussions on business usage, but how can we monitor in real-time whether we’re getting close to the available allotment and take action as necessary?
If you’re using BI4 then the functionality is built directly into the Monitoring application available out of the box. By creating a watch, and a derived metric if you have more than 1 CMS in your cluster, the platform can alert a group of administrators if concurrent usage exceeds a defined threshold. You can even have an action take place when the alert is triggered, such as restarting one or more of the CMS in the cluster to flush any inactive sessions that haven’t reached timeout.
In the screenshot above I configured a derived metric called ‘Total Concurrent Sessions’ and set the value to:
CMSA.CentralManagementServer$’Number of Sessions Established by Concurrent Users’+ CMSB.CentralManagementServer$’Number of Sessions Established by Concurrent Users’
To get the total number of logged on concurrent sessions for the entire cluster. I then created a watch to “caution” once the number of sessions reaches 200, and trigger a “danger” alert when the number reaches 300. The rich functionality available in the monitoring plugin is just one of the many benefits available in BI4, and I encourage everybody to strongly consider upgrading if you haven’t done so already.
That being said, many customers are well established on XI3.1 and will remain there for the immediate future. Although it lacks the robust monitoring solution available in BI4, there is a fairly simple way to monitor concurrent session usage in real-time through the use of a custom Java Program Object. I will demonstrate the method for writing such a program object below, along with steps to implement email notification in case a threshold has been exceeded.
XI3.1 Session Monitoring
First and foremost, I would not have been able to accomplish this without the excellent program object sample found in SAP Note 1578811. This “shell” is extremely helpful for providing a framework in which more complicated logic can be built. This sample program accepts a single numeric argument from the CMC and uses that to determine whether or not to fail the job, which in turn triggers an email alert.
The sample code is below (There is a scrollbar at the bottom of the post and copy and paste should contain the entire block of sample code):
// JRapp - 5/2/2012 - Concurrent Session count for monitoring of license consumption
package com.sap.sample;
import com.crystaldecisions.sdk.properties.*;
import com.crystaldecisions.sdk.exception.SDKException;
import com.crystaldecisions.sdk.framework.IEnterpriseSession;
import com.crystaldecisions.sdk.occa.infostore.IInfoStore;
import com.crystaldecisions.sdk.occa.infostore.IInfoObjects;
import com.crystaldecisions.sdk.occa.infostore.IInfoObject;
import com.crystaldecisions.sdk.plugin.desktop.program.IProgramBaseEx;
import com.crystaldecisions.sdk.occa.infostore.CePropertyID;
import com.crystaldecisions.sdk.plugin.desktop.connection.IConnection;
public class CSCount implements IProgramBaseEx
{
public void run(IEnterpriseSession enterpriseSession,IInfoStore infoStore,IInfoObject programInfoObject,java.lang.String objectID,java.lang.String[] args) throws SDKException
{
// Indicate that we would like to allow for us to set the status of this program object to "Failed" if an error
// occurs during the processing of the program object.
programInfoObject.getProcessingInfo().properties().add("SI_PROGRAM_CAN_FAIL_JOB", Boolean.TRUE, IProperty.DIRTY);
programInfoObject.save();
// When the status of a completed Java Program Object is "Success", any text that is written to
// System.out.println(...) will be available to be viewed in the CMC by going to the History
// of the Java Program Object and clicking on the date under the "Instance Time" column for the
// successful object.
System.out.println("Start Concurrent Session count.");
// Query the Infostore for the number of concurrent sessions
try
{
IInfoObjects connections = infoStore.query("SELECT count(SI_ID) FROM CI_SYSTEMOBJECTS WHERE SI_KIND = 'Connection' AND SI_FAILOVER_AVAILABLE_UNTIL = NULL AND SI_AUTHEN_METHOD != 'server-token'");
IInfoObject cscount = (IInfoObject) connections.get(0);
IProperties counts = cscount.properties().getProperties("SI_AGGREGATE_COUNT");
int idCount = (int)counts.getInt("SI_ID");
// JRapp 5/3/2012 - compare session count with threshold argument
int threshold = Integer.parseInt(args[0]);
if(idCount > threshold)
{
// Check the number of concurrent sessions and throw an exception if it exceeds the threshold
// passed in as an argument via the CMC
throw new Exception("Warning: Concurrent Sessions exceeds defined threshold of: " + threshold + " Value is: " + idCount);
}
else
{
System.out.println("Sessions do not exceed "+ threshold);
System.out.println("Session count is: " + idCount);
}
}
catch (Exception ex)
{
// We catch an exception here. When there is an exception, we are going to
// treat that as a program error. When there is a program error, we want
// the program object instance to have a Status of "Failed". In order to do
// that, we write "PROCPROGRAM:PROGRAM_ERROR" and "62009" to the System.out
// and then we can write up to 3 lines to the System.out.
// At the end, we do a System.exit(1) and the Status of this program
// object will now be "Failed".
System.out.println("PROCPROGRAM:PROGRAM_ERROR");
System.out.println("62009");
// On the first line, print out the error to the System.out:
// The first line appears as the error message when the "FAILED" status
// of the instance is clicked on the History page.
System.out.println(ex);
// We will print out up to two extra lines of information. These two
// extra lines are not seen when clicking on the "FAILED" status on the
// instance History page
// All three lines of information can be seen in the SI_STATUSINFO property
// for the program instance object.
System.out.println("CS Threshold Exceeded");
// Exit the system so that the Status is set to "Failed".
System.exit(1);
}
}
}
The sample code is fairly well commented so hopefully it needs no additional explanation. You can copy the source and save it into a text file called CSCount.java so that it matches the class name defined above. The number of sessions will be logged to the stdout of the scheduled instance, but it might be more desirable to write to a common location using log4j. To implement log4j in the sample above please refer to SAP Note 1582714 for assistance.
Once the file is saved it will need to be compiled into a class file. The easiest way to do this is to copy the CSCount.java file into the javasdk/bin directory of the XI3.1 installation. It is important that we compile the class using the same version of the Java SDK available to the Program Job Server, otherwise we’re at risk of it failing due to incompatibility between versions. In a default installation of SAP BusinessObjects Enterprise XI3.1 on Windows 2003 the complete directory is:
C:\Program Files\Business Objects\javasdk\bin
The next step in the process is to compile the source code into a class file. Perform the following steps:
- Launch a command prompt: Start > Run > cmd
- Change to the javasdk/bin directory: cd C:\Program Files\Business Objects\javasdk\bin
- Compile the source code using the javac command: javac -cp “C:\Program Files\Business Objects\common\4.0\java\lib\cecore.jar;C:\Program Files\Business Objects\common\4.0\java\lib\cesession.jar;C:\Program Files\Business Objects\common\4.0\java\lib\ceplugins_core.jar;C:\Program Files\Business Objects\common\4.0\java\lib\ceplugins_client.jar;C:\Program Files\Business Objects\common\4.0\java\lib\celib.jar” CSCount.java
The classpath specified by -cp directs the compiler to the necessary class files required by the source code. If successful, a file called CSCount.class will be created in the same folder. The next step in the process is to create a jar file that can be scheduled in the CMC. To do this, we must create a directory structure that matches the package name in the code, com.sap.sample. Create a series of folders within the javasdk/bin directory that results in the following path:
C:\Program Files\Business Objects\javasdk\bin\com\sap\sample
And move the CSCount.java and CSCount.class files there.
From the command line, execute the following command:
jar -cvf CSCount.jar ./com/sap/sample/CSCount*
This should result in a file called CSCount.jar in the javasdk/bin directory. Next, publish the jar file to XI3.1 using the steps outlined in SAP Note 1199532. For the purposes of this blog I have published CSCount.jar to the Administration Tools folder that contains other scripts and programs.
Finally, set up a recurring schedule to run at an interval of your choice. This could be every minute, every 15 minutes, every hour, etc. When scheduling based on a very short interval, such as every minute, be sure to set up instance limits to prevent too many historical instances from accumulating.
Modify the following program parameters under “Schedule” to match your environmental needs:
Arguments: 300
A single integer based argument that sets the concurrent session threshold. You can test failure notification by scheduling with a value of 0. A session count higher than this number will cause the job to fail.
Class to run: com.sap.example.CSCount
The complete name of the java class for the program job server to execute.
Classpath: C:\Program Files\Business Objects\common\4.0\java\lib\cecore.jar;C:\Program Files\Business Objects\common\4.0\java\lib\cesession.jar;C:\Program Files\Business Objects\common\4.0\java\lib\ceplugins_core.jar;C:\Program Files\Business Objects\common\4.0\java\lib\ceplugins_client.jar;C:\Program Files\Business Objects\common\4.0\java\lib\celib.jar
The list of jar file dependencies the program has.
The program is now ready to run. If desired, configure Failure Notification so that an administrator can be emailed when the defined threshold is exceeded. Instructions for configuring failure notification can be found in the Administrator’s Guide under the chapter “Setting notification for the success or failure of a scheduling job”
I hope you’ve found this post and sample program useful. There are a wealth of administrative tasks that can be performed using Program Objects and it would be great to see some innovation from the Ecosystem on this subject.
Thanks for this blog.
Very usefull.
IMHO - New concurrent session model is more expensive than old CPU model.
Hi Mikhail, It Actually is not more expensive- it's cheaper. We don't charge for professional license to create reports, and then the view license on top. Now one Name User or CSBL can create and view a report.
You also have the added benefit of building your system without worry about CPU calculations. So CSBL is much more customer friendly.
Do check with your account team for more details.
Regards,
Steve Bickerton
Thanks for this - useful stuff. A couple of comments:-
1) The SAP note for deploying the Jar file is for BO XI R2, for R3 I used the "Folders" option in the CMC to do something similar
2) Class to run: com.sap.example.CSCount should be Class to run: com.sap.sample.CSCount
based on the instructions for creating the Jar.
Thanks Daniel. I will be sure to update the class name.
You can also refer to SAP Note 1546736 for the XI3.1 steps.
As you've responded can I pick your brains for how I can implement this differently? 🙂
I have done this as described on a BO XI R3 system using the Java script as is. Then I have set the schedule and tested the output. This works great.
Now what I'd like to do is any time the threshold is exceeded on a run for an email to be sent to an address with details of the number of users and threshold breached. I don't want an email sent if the threshold isn't broken.
So currently I set Notification on Error to be Email and this works. I get an email when the threshold is broken, but with no information other than that which I specifically hardcode into the notification pane. How can I also pass through the exception output to the email?
I updated the sample to ensure XI 3.1 uses the same query as the CMC > Session section:
IInfoObjects connections = infoStore.query("SELECT count(SI_ID) FROM CI_SYSTEMOBJECTS WHERE SI_KIND = 'Connection' AND SI_FAILOVER_AVAILABLE_UNTIL = NULL AND SI_AUTHEN_METHOD != 'server-token'");
Hello,
I am wondering something in BI 4 : what is the difference between those 2 metrics :
- CMS.Number of session established by concurrent users
- CMS.Number of session established by all users
Thanks for your answer if you have one!
Hi Antoine,
It is possible to have both concurrent and named users so the first metric is how many sessions by concurrent users only, the 2nd metric would represent the sum of both concurrent and named users. If you don't have any named users it is likely that these numbers will be the same.
"Number of sessions established by concurrent users" in the metrics of individual CMS  in a clustered environment shows the count equal to number of sessions seen in CMC>Sessions(Which shows the sessions created by all  CMS  in the cluster as well).
Because of this , If we configure a Derived metric to count the number of concurrent sessions created by all the CMS, The session count shown by metric is <Number of CMS>* Sessions seen in CMC>Sessions.
So, It seems that every CMS has the count of sessions established by other CMS in the cluster.
Could you Please clarify on Why is it required to  sum the number of concurrent sessions established by all the CMS in the cluster.
I think because of this summation, the derived metric is evaluating the incorrect session counts.