Cisco CUCM – Reports from SQL (show risdb)

Hey guys,

In my last post, I gave you some tips on how pull CDRs out from CUCM using SQL commands (Cisco CUCM – CDR through SQL). Today, I’m going to show other useful reports you can get using SQL commands.

As we are getting all the information from a CLI command, you will need to export the data to an excel file  to create something nice to be presented….or even use Python, PHP, to create something automatic for you.

Today I’m going to focus on one command, but with different variables and outputs: show risdb
This command displays RIS database table information.

Parameters

list : displays the tables that are supported in the Realtime Information Service (RIS) database.
query : displays the contents of the RIS tables

So, if you enter the command show risdb list, you will see a list of options in the table that you can explore.

image

The most common, and used, is the Phone.
To access this table, you must use this command: show risdb query phone.

image

This command is so powerful and useful!!! Here we see everything related to your phones: DeviceName, Descr, Ipaddr, Ipv6addr, Ipv4Attr, Ipv6Attr, MACaddr, RegStatus, PhoneProtocol, DeviceModel, HTTPsupport, #regAttempts, prodId, username, seq#, RegStatusChg TimeStamp, IpAddrType, LoadId, ActiveLoadId, InactiveLoadId, ReqLoadId, DnldServer, DnldStatus, DnldFailReason, LastActTimeStamp, Perfmon Object.

In other words, you can have a list of devices in your Cluster, check each phone is currently Registered or Unregistered, and its information such as IP, Protocol, Model……an excellent Report Smile

But, if you want to explore it a bit more, there are other interesting queries!
For example, if you want to have a report about your SIP Trunks, you can use this command: show risdb query sip.

Here you have information about your SIP Trunk, such as name, IPs, descriptions, Status, Peer Status.

This is the Trunk on CUCM:

image

image

The Status column (in red) corresponds to the “Service Status” field visible near the top of CCMAdmin’s SIP Trunk page.

0 – No service (The Trunk peer is reachable via TCP, but SIP Options ping is failing)
1 – Full service (All Trunk peers are up and SIP Options ping is successful)
2 – Partial service (A subset of Trunk peers are unreachable)
3 – Unknown (The Trunk peer is unreachable via TCP, or SIP Options ping is not enabled)

image

The PeerStatus column (in blue) corresponds to the “Status” field for each peer on the SIP Trunk page (near the bottom).

0 – Down
1 – Up

Now it’s up to you to choose a query from RSIDB list and start to explore it. You will find interesting options there, like CTIs, Gateways…..

Hope you’ve enjoyed it Smile

See ya!

Bruno

Cisco CUCM – CDR through SQL

Hey everybody,

Today’s post is going to be quick, but may give you some good tips Smile
Last week I got some requests from a Customer, and he needed to know which extensions were recently being used . In order to save licenses, he wanted to delete all phones/lines that weren’t being used.

CDRs on CUCM is a nightmare in my opinion. Mainly when you need to check lots of lines, for a long period.
That’s why I decide to pull this information out directly from SQL.

So here are some useful commands to get CDRs from SQL, and depending on your needs and knowledge, you can use Python or other language to built your own CDR Reporting Smile

First of all, to use the commands you need to ensure that the following steps are taken on your CUCM system:

  1. Activate the CDR Analysis and Reporting (CAR) service on the CUCM publisher node.
  2. Go to System > Service Parameters and set the Cisco Call Manager service “Call Diagnostics Enabled” parameter to true on every cluster node that has the Call Manager service activated.

Now, going to SQL, this is the structure of any SQL Command on CUCM:
admin: run sql select [field list] from [table] where [expression]

The table we are going to use is tbl_billing_data. This table stores all of the elements we need to accomplish the task at hand.

So this is going to be our syntax: run sql select + column + from tbl_billing_data + where + column + (like,in,between,etc).

PS: Please not this command is only acceptable on Publisher.

In my example, I want to get Date (TimeStamp) , Calling and Called Number of all calls from extensions which have “702709” in their numbers and happened this month.

The date must be sent in TimeStamp mode. I use THIS SITE to convert normal date to Timestamp, and vice versa. If you were pulling CDR data into Excel then you can use the following formula (in a new cell) to do the conversion:
=(((A1-(6*3600))/86400)+25569)

Right, so this is the command:

run sql car select datetimeOrigination,callingPartyNumber,finalCalledPartyNumber from tbl_billing_data where callingpartynumber like ‘%702709%’ and datetimeconnect > ‘1630486076’

And here is the result:

image
Well, now you can explore and play a bit more, depending on your needs. You can add more columns, like duration, destIpAddr, callingPartyNumber_uri, originalCalledPartyPattern,callingPartyNumberPartition,EU_SIP_SME_NOS….

That’s it guys. As I said, it was really quick Smile

Hope you’ve enjoyed!

Bruno

UCCX – Queries using Python Script

Hey guys,

As promised in my post about ODBC Connection, (you can read it HERE), I’m going to show you how to create a basic Script using Python to query some information from UCCX, which can be useful to create some personalized Dashboards.

Even though we have many types of reports on CUIC, sometime they don’t meet our expectations by having too much unnecessary information or by lack of information.

I’ have decided to use Python, along with HTML, to create my own Dashboard. So I can have only information I know is 100% useful.

First of all, you have to create the ODBC connection to the server where you are going to place the script.
Again, you can use THIS POST to help you out.

Once you have the ODBC Connection working, it’s time to work on your script.

To be able to connect your script to your ODBC, you need to have a PYODBC python Library installed. To be able to better manipulate date and time, I’m also using datetime library.

The first part of the script is used to establish a connection to your ODBC. So you need to fill all its information in the connection strings. It’s important to mention that pyodbc does not even look at the connection string. It is passed directly to the database driver.

To start off my code, I’ll call the libraries and use the command conn = pyodbc.connect to connect to my ODBC.

image

Connection is now ready!
Now it’s time to choose a query to be sent. That query is sent using SQL commands.
This means you can use your SQL skills to play with queries and create interesting reports

Smile

In the below example, I wanted to know how many licenses are being consumed daily.
To do that, I’ll use the SQL command: ” {call sp_license_utilization(‘2021-05-05 00:00:01′,’2021-05-05 23:00:01′,’0′,’1’)}”. The line in the script will be like that:

cursor.execute(” {call sp_license_utilization(‘2021-05-05 00:00:01′,’2021-05-05 23:00:01′,’0′,’1’)}”)

If you print the result, you will see something like that:

[(datetime.datetime(2021, 4, 16, 0, 0, 1), 1, 0, 3), (datetime.datetime(2021, 4, 16, 1, 0, 1), 0, 0, 4), (datetime.datetime(2021, 4, 16, 2, 0, 1), 0, 0, 4), (datetime.datetime(2021, 4, 16, 3, 0, 1), 0, 0, 4), (datetime.datetime(2021, 4, 16, 4, 0, 1), 1, 0, 6), (datetime.datetime(2021, 4, 16, 5, 0, 1), 0, 0, 18), (datetime.datetime(2021, 4, 16, 6, 0, 1), 2, 0, 43), (datetime.datetime(2021, 4, 16, 7, 0, 1), 4, 0, 58), (datetime.datetime(2021, 4, 16, 8, 0, 1), 9, 0, 63), (datetime.datetime(2021, 4, 16, 9, 0, 1), 6, 0, 64), (datetime.datetime(2021, 4, 16, 10, 0, 1), 5, 0, 62), (datetime.datetime(2021, 4, 16, 11, 0, 1), 4, 0, 51), (datetime.datetime(2021, 4, 16, 12, 0, 1), 5, 0, 51), (datetime.datetime(2021, 4, 16, 13, 0, 1), 4, 0, 49), (datetime.datetime(2021, 4, 16, 14, 0, 1), 4, 0, 39), (datetime.datetime(2021, 4, 16, 15, 0, 1), 3, 0, 27), (datetime.datetime(2021, 4, 16, 16, 0, 1), 2, 0, 15), (datetime.datetime(2021, 4, 16, 17, 0, 1), 0, 0, 10), (datetime.datetime(2021, 4, 16, 18, 0, 1), 1, 0, 8), (datetime.datetime(2021, 4, 16, 19, 0, 1), 0, 0, 6), (datetime.datetime(2021, 4, 16, 20, 0, 1), 0, 0, 6), (datetime.datetime(2021, 4, 16, 21, 0, 1), 0, 0, 6), (datetime.datetime(2021, 4, 16, 22, 0, 1), 0, 0, 5), (datetime.datetime(2021, 4, 16, 23, 0, 1), 0, 0, 5)]

Then, use Python to manipulate the results according to your needs. In my case, I’m using the datetime to get today’s date. I also created a list to save the values, as this code will check the license each hour, and give me the maximum as a final result.

The full code for this sample is:

image

 

import pyodbc
from datetime import datetime

conn = pyodbc.connect(‘DRIVER={IBM INFORMIX ODBC DRIVER};’
‘UID=uccxhruser;PWD=123456;’
‘DATABASE=db_cra;’
‘HOST=uccxlab.com;’
‘SERVER=uccxlab_uccx;’
‘SERVICE=1504;PROTOCOL=onsoctcp;CLIENT_LOCALE=en_US.UTF8;DB_LOCALE=en_US.UTF8’)
cursor = conn.cursor()

listItem = []
listLicCCX = []
timestampStr = datetime.now().strftime(“%Y-%m-%d”)

try:
cursor.execute(” {call sp_license_utilization(‘” + str(timestampStr) + ” 00:00:01′,'” + str(timestampStr) + ” 23:59:59′,’0′,’1’)}”)
rows = cursor.fetchall()
LicenseUsage = rows
for hourly in LicenseUsage:
if hourly[3] != None:
listItem.insert(0, hourly[3])
else:
listItem.insert(0, 0)
except pyodbc.Error as ex:
print(“An exception occurred”)
listItem.insert(0, 0)
listLicCCX.insert(0, (max(listItem)))

print(listLicCCX)

And this is the final result:

image

Remember you can use any SQL Query!

For example, this is the SQL query to get a list of Agents by Team:select s.resourceLoginID,s.resourceFirstName,s.resourceLastName,s.extension, t.teamname from Resource s inner join team t on s.assignedTeamID = t.teamid where s.active = ‘t’ and t.active = ‘t’ and t.teamname = ‘UCCX_TEAM’ order by t.teamname, s.resourceloginid

Using a simple Select * from rtcsqssummary here csqname = ‘<CSQ Name>’ query you can display more information as this query will return the following information.

csqname
loggedinagents
availableagents
unavailableagents
totalcalls
oldestcontact
callshandled
callsabandonded
callsdequeued
avgtalkduration
avgwaitduration
longesttalkduration
longestwaitduration
callswaiting
enddatetime
workingagents
talkingagents
reservedagents
startdatetime
convavgtalkduration
convavgwaitduration
convlongestwaitduration
convlongestwaitduration
convoldestcontact

The sky is the limit!

Smile

Now that you now how to use SQL queries in Python, you can start creating your own script!

Enjoy!

Bruno