Author Topic: Cannot get count of agents on breaks using statserver CurrNumberNotReadyStatuses  (Read 3666 times)

Offline merve.ugursac

  • Newbie
  • *
  • Posts: 11
  • Karma: 0
Hello everyone,

What I want to do is, when a call is waiting on a virtual queue, I need the count of agents on breaks of that particular queue.  > Break : 3, LunchBreak :4
I have definitions on statServerReporting filters, for all notready statues such as below.
AUX_RC_1 : PairExist("Lunch Break",Lunch Break")
AUX_RC_2 : PairExist("Meeting",Meeting")
AUX_RC_3 : PairExist("Break",Break") etc.
I have this piece of code on statServerProtocol.Received event, for every virtual queue on the system.
The problem is I can not get the count on the row "int count = Convert.ToInt32(@event.StringValue);",,  it is always empty .

Can anyone lead me on what I do wrong?


breakNames : string array (AUX_RC_1, AUX_RC_2, AUX_RC_3 )

[quote]

                    var requestOpenStatistic = RequestOpenStatistic.Create();
                    requestOpenStatistic.StatisticObject = StatisticObject.Create();
                    requestOpenStatistic.StatisticObject.ObjectType = StatisticObjectType.GroupAgents;
                    requestOpenStatistic.StatisticObject.TenantName = "Environment";
                    requestOpenStatistic.StatisticObject.TenantPassword = "";
                    requestOpenStatistic.StatisticMetric = StatisticMetric.Create();
                    requestOpenStatistic.StatisticMetric.StatisticType = "CurrNumberNotReadyStatuses";
                    requestOpenStatistic.Notification = Notification.Create();
                    requestOpenStatistic.Notification.Mode = NotificationMode.Immediate;

for (int i = 0; i < breakNames?.Length; i++)
{
string breakName = breakNames[i].TrimStart().TrimEnd();

requestOpenStatistic.ReferenceId = queueStatisticId++;
requestOpenStatistic.StatisticObject.ObjectId = agentGroupName ; //"Corporate" agent.agentGroup

requestOpenStatistic.StatisticMetric.Filter = breakName; // NotReadyStatus : Mola, Egitim, Yemek Molası vb.                   
 

var response = StatProtocol.Request(requestOpenStatistic);

if (response == null || response.Id != EventStatisticOpened.MessageId)
{
// response.Id : 1 > EventError
// response.Id : 2 > EventInfo
// response.Id : 22 > EventStatisticOpened
CustomLogger.Instance().Error(methodName, new Exception($" - StatServer bağlantı hatası - RequestOpenStatistic failed. - StatProtocol.State : {StatProtocol.State} - response.Id : {response.Id} - agentGroupName :{agentGroupName} - breakName : {breakName} - Message : {response.Name} - ProtocolDescription : {response.ProtocolDescription}"));
}
else
{
var @event = response as EventStatisticOpened;
int count = Convert.ToInt32(@event.StringValue);

CustomLogger.Instance().Info($" - OnWaitingCallsEventInfo - {methodName} - stat sorgu sonucu -> @event.StringValue:  {@event.StringValue}-  @event.ReferenceId : {@event.ReferenceId}");
CustomLogger.Instance().Info($" - OnWaitingCallsEventInfo - {methodName} - agentGroupName : {agentGroupName}-  breakName : {breakName}, count : {count}");

if (count > 0)
{
result.Add(new AgentBreakModel
{
Count = count,
Status = breakName, // breakName "AUX_RC_3"    (AUX_RC_3 => Break )
StatusDescription = "" // "Break"
});

CustomLogger.Instance().Info($" - OnWaitingCallsEventInfo - {methodName} - AgentBreakModel eklendi : agentGroupName : {agentGroupName} - breakName : {breakName} - count : {count} ");
}
}

}


[/quote]

Offline hsujdik

  • Hero Member
  • *****
  • Posts: 541
  • Karma: 30
Probably because you are casting response as EventStatisticOpened. The class that has the actual value is EventInfo, and you have to match it against the REQ_ID (ReferenceId of the RequestOpenStat/Ex that you are holding in your variable queueStatisticId) to know about which Statistic it refers to

Offline merve.ugursac

  • Newbie
  • *
  • Posts: 11
  • Karma: 0
Hey, I am grateful for your response. Thank you. But it is EventStatisticOpened. (I tried EventInfo too neveretheless).

Here are the logs. My agent is on "Break" break type which maps to AUX_RC_3, I was expecting to see "1" (@event.StringValue: 1 ) as count but it is "" ( @event.StringValue:  )
AUX_RC_3 : PairExist("Break","Break")

2022-04-02 12:44:16,605: [ INFO] -----> EventStatisticOpened geldi
2022-04-02 12:44:16,605: [ INFO]  - OnWaitingCallsEventInfo - GetAgentCountPerBreak() - stat sorgu sonucu -> @event.StringValue:  -  @event.ReferenceId : 2
2022-04-02 12:44:16,605: [ INFO]  - OnWaitingCallsEventInfo - GetAgentCountPerBreak() - agentGroupName : TestCampaign-  breakName : AUX_RC_3, count : 0
2022-04-02 12:44:16,605: [ INFO]  - OnWaitingCallsEventInfo - GetAgentCountPerBreak() - AgentBreakModel eklendi : agentGroupName : TestCampaign - breakName : AUX_RC_3 - count : 0
« Last Edit: April 02, 2022, 09:50:31 AM by merve.ugursac »

Offline hsujdik

  • Hero Member
  • *****
  • Posts: 541
  • Karma: 30
Hi,

I have put together a small example code for you to use as a reference:


[code]
using Genesyslab.Platform.Commons.Protocols;
using Genesyslab.Platform.Reporting.Protocols;
using Genesyslab.Platform.Reporting.Protocols.StatServer;
using Genesyslab.Platform.Reporting.Protocols.StatServer.Events;
using Genesyslab.Platform.Reporting.Protocols.StatServer.Requests;
using System;
using System.Collections.Generic;

namespace StatServerReasonCode
{
    class Program
    {
        static Dictionary<int, Tuple<string, string>> referenceIds = new Dictionary<int, Tuple<string, string>>();

        static void Main(string[] args)
        {
            string statServerHost = "10.131.3.101";
            int statServerPort = 7000;

            StatServerProtocol exampleProtocol = new StatServerProtocol(new Endpoint(statServerHost, statServerPort));
            // Specifies a method to handle non-request related messages
            exampleProtocol.Received += statServer_StatReceived;
            exampleProtocol.Open();

            // All your Groups that you want to monitor
            HashSet<string> agentGroups = new HashSet<string>
            {
                "Group1",
                "Group2",
                "Group3",
                "Group4"
            };

            // All filters that you want to apply to your Statistic Type in separate statistics
            HashSet<string> filters = new HashSet<string>
            {
                "AUX_RC_1",
                "AUX_RC_2",
                "AUX_RC_3"
            };

           
            foreach (string groupName in agentGroups)
            {
                foreach (string filter in filters)
                {
                    // This is used to get which object/filter when the EventInfo is received.
                    // Will later be added to the static dictionary referenceIds to be retreived later on the
                    // Message handler "statServer_StatReceived" method
                    Tuple<string, string> agentGroupAndFilter = new Tuple<string, string>(groupName, filter);
                   
                    StatisticObject statObject = StatisticObject.Create();
                    statObject.ObjectType = StatisticObjectType.GroupAgents;
                    statObject.TenantName = "Environment";
                    statObject.ObjectId = agentGroupAndFilter.Item1;
                   
                    StatisticMetric statMetric = StatisticMetric.Create();
                    statMetric.StatisticType = "CurrNumberNotReadyStatuses";
                    statMetric.Filter = agentGroupAndFilter.Item2;

                    Notification statNotification = Notification.Create();
                    statNotification.Mode = NotificationMode.Immediate;
                    statNotification.Insensitivity = 1;

                    RequestOpenStatistic requestOpenStatistic = RequestOpenStatistic.Create();
                    requestOpenStatistic.StatisticObject = statObject;
                    requestOpenStatistic.StatisticMetric = statMetric;
                    requestOpenStatistic.Notification = statNotification;

                   
                    IMessage response = exampleProtocol.Request(requestOpenStatistic);
                    referenceIds.Add(requestOpenStatistic.ReferenceId, agentGroupAndFilter);

                    switch(response.Name)
                    {
                        case "EventStatisticOpened":
                            Console.WriteLine($"Registered statistic for object {groupName} and filter {filter}");
                            break;
                        case "EventError":
                            Console.WriteLine($"Error opening statistic for object {groupName} and filter {filter}");
                            break;
                    }
                   
                }
               
            }

        }

        private static void statServer_StatReceived(object sender, EventArgs e)
        {
            IMessage message = ((MessageEventArgs)e).Message;

            // Discard messages that are not of type "EventInfo" (message that contains statistic values)
            if (!message.Name.Equals("EventInfo", StringComparison.InvariantCultureIgnoreCase)) return;
            EventInfo eventInfo = (EventInfo)message;

            // Discard messages that are not about a statistic that we are waiting for the data
            if (!referenceIds.ContainsKey(eventInfo.ReferenceId)) return;

            // Get the group/filter combination based on the ReferenceId of the received message
            Tuple<string, string> agentGroupAndFilter = referenceIds[eventInfo.ReferenceId];

            string groupName = agentGroupAndFilter.Item1;
            string filter = agentGroupAndFilter.Item2;

            Console.WriteLine($"Received current value of group {groupName}, filter {filter}: {eventInfo.IntValue}");
        }
    }
}

[/code]


Regards,
HDS

Offline merve.ugursac

  • Newbie
  • *
  • Posts: 11
  • Karma: 0
Hi,

I appreciate the effort you've put in to help me! Thank you very much! I can get the count now on a sample project that represents mine.

The problem now is, I need the count in an immediate call since on protocol received I read the call count waiting on each virtual queue. Inside this function I need an immediate request-response of this agent-break counts. That was why I had tried to read the response immediately afterwards.  I have adjusted my code to read both queries on statProtocol.received but the response of the agentcount is not available when I need that since its not immediate this way.

Do you think there is a way to accomplish this?


For the following :
907 is my virtual queue and result : 1 because I am on the line and the agent of this queue is on break (AUX_RC_3 which will be queried with a referanceId of  10002), so I need the count of agents who are under this virtQueue.


2022-04-04 10:26:56,579: [ INFO] OnWaitingCallsEventInfo()- result : 1 referanceId : 907
2022-04-04 10:26:56,579: [ INFO] OnWaitingCallsEventInfo()- referanceId (queue.DbId) : 907 için result : 1, queue.QueueName :VQ_TestCampaign, queue.QueueMaxAgent :0.
2022-04-04 10:26:56,583: [ INFO] GetCampaingNameFromVirtualQueueId() - QueueId : 907 ,  VQ_TestCampaign - virtualQueue.Switch.Name : SIPSwitch_DR , AgentGroupName Found : TestCampaign
2022-04-04 10:26:56,886: [ INFO]  - OnWaitingCallsEventInfo -  Agents on break : []  [b] I needed the count here [/b]
2022-04-04 10:26:56,886: [ INFO]  - OnWaitingCallsEventInfo -  -- ResultValues , IsCallFirstCall false , FirstCallTime: 4.04.2022 10:26:56
2022-04-04 10:26:56,886: [ INFO] OnWaitingCallsEventInfo()- result : 0 referanceId : 10000  [b] --> AUX_RC_1[/b]
2022-04-04 10:26:56,886: [ INFO] OnWaitingCallsEventInfo()- result : 0 referanceId : 10001  [b]--> AUX_RC_2[/b]
2022-04-04 10:26:56,886: [ INFO] OnWaitingCallsEventInfo()- result : 1 referanceId : 10002  [b] --> AUX_RC_3 --> but I got it here[/b]
2022-04-04 10:26:56,889: [ INFO] OnWaitingCallsEventInfo()- result : 0 referanceId : 10003  [b]--> AUX_RC_4[/b]


Long story short, I need the reponse here :

[code]
switch (response.Name)
                            {
                                case "EventStatisticOpened":
                                    Console.WriteLine($"{methodName} - Registered statistic for object {agentGroupName} and filter {agentGroupAndFilter}");  [b]--> here [/b]
                                    break;
                                case "EventError":
                                    Console.WriteLine($"{methodName} - Error opening statistic for object {agentGroupName} and filter {agentGroupAndFilter}");
                                    break;
                                default:
                                    Console.WriteLine($"{methodName} - response.Name  : {agentGroupName} and filter {agentGroupAndFilter}");
                                    break;
                            }

[/code]

« Last Edit: April 04, 2022, 08:32:03 AM by merve.ugursac »

Offline merve.ugursac

  • Newbie
  • *
  • Posts: 11
  • Karma: 0
I have found "RequestPeekStatistic" to get immediate information on a statistic, but I couldn't figure out how to get response.
document link : https://docs.genesys.com/Documentation/PSDK/9.0.x/Developer/StatServer

I have added the below code
[code]

switch (response.Id)
                            {
                                case EventStatisticOpened.MessageId:
                                    {
                                        Console.WriteLine($"{methodName} - EventStatisticOpened - Registered statistic for object {agentGroupName} and filter {agentGroupAndFilter}");

                                        RequestPeekStatistic req = RequestPeekStatistic.Create();
                                        req.StatisticId = requestOpenStatistic.ReferenceId;
                                        StatProtocol.Send(requestOpenStatistic);     

                                        CustomLogger.Instance().Info($"{methodName} - Response Peek : {requestPeek}");                             
                                    }
                                    break;
                                case EventError.MessageId:
                                    Console.WriteLine($"{methodName} - Error opening statistic for object {agentGroupName} and filter {agentGroupAndFilter}");
                                    break;
                            }   

[/code]


But I get the empty result again. I presume to get the count here > message attributes:

2022-04-04 15:44:06,688: [ INFO] GetAgentCountPerBreak() - response : 'EventStatisticOpened' ('22')
message attributes:
REQ_ID [int]    = 10002
USER_REQ_ID [int] = 0
TM_SERVER [int] = 1649076246
TM_LENGTH [int] = 0
LONG_VALUE [int] = 0

2022-04-04 15:44:06,688: [ INFO] GetAgentCountPerBreak() - response.Id : 22 - agentGroupName :TestCampaign - breakName : AUX_RC_3 - Message : EventStatisticOpened - ProtocolDescription : Reporting.StatServer
2022-04-04 15:44:06,688: [ INFO] GetAgentCountPerBreak() - Response Peek : 'RequestPeekStatistic' ('1027')
message attributes:
ASSOC_REQ_ID [int] = 10002

Offline hsujdik

  • Hero Member
  • *****
  • Posts: 541
  • Karma: 30
[quote author=merve.ugursac link=topic=12271.msg54748#msg54748 date=1649058412]
Hi,

I appreciate the effort you've put in to help me! Thank you very much! I can get the count now on a sample project that represents mine.

The problem now is, I need the count in an immediate call since on protocol received I read the call count waiting on each virtual queue. Inside this function I need an immediate request-response of this agent-break counts. That was why I had tried to read the response immediately afterwards.  I have adjusted my code to read both queries on statProtocol.received but the response of the agentcount is not available when I need that since its not immediate this way.

Do you think there is a way to accomplish this?


For the following :
907 is my virtual queue and result : 1 because I am on the line and the agent of this queue is on break (AUX_RC_3 which will be queried with a referanceId of  10002), so I need the count of agents who are under this virtQueue.


2022-04-04 10:26:56,579: [ INFO] OnWaitingCallsEventInfo()- result : 1 referanceId : 907
2022-04-04 10:26:56,579: [ INFO] OnWaitingCallsEventInfo()- referanceId (queue.DbId) : 907 için result : 1, queue.QueueName :VQ_TestCampaign, queue.QueueMaxAgent :0.
2022-04-04 10:26:56,583: [ INFO] GetCampaingNameFromVirtualQueueId() - QueueId : 907 ,  VQ_TestCampaign - virtualQueue.Switch.Name : SIPSwitch_DR , AgentGroupName Found : TestCampaign
2022-04-04 10:26:56,886: [ INFO]  - OnWaitingCallsEventInfo -  Agents on break : []  [b] I needed the count here [/b]
2022-04-04 10:26:56,886: [ INFO]  - OnWaitingCallsEventInfo -  -- ResultValues , IsCallFirstCall false , FirstCallTime: 4.04.2022 10:26:56
2022-04-04 10:26:56,886: [ INFO] OnWaitingCallsEventInfo()- result : 0 referanceId : 10000  [b] --> AUX_RC_1[/b]
2022-04-04 10:26:56,886: [ INFO] OnWaitingCallsEventInfo()- result : 0 referanceId : 10001  [b]--> AUX_RC_2[/b]
2022-04-04 10:26:56,886: [ INFO] OnWaitingCallsEventInfo()- result : 1 referanceId : 10002  [b] --> AUX_RC_3 --> but I got it here[/b]
2022-04-04 10:26:56,889: [ INFO] OnWaitingCallsEventInfo()- result : 0 referanceId : 10003  [b]--> AUX_RC_4[/b]


Long story short, I need the reponse here :

[code]
switch (response.Name)
                            {
                                case "EventStatisticOpened":
                                    Console.WriteLine($"{methodName} - Registered statistic for object {agentGroupName} and filter {agentGroupAndFilter}");  [b]--> here [/b]
                                    break;
                                case "EventError":
                                    Console.WriteLine($"{methodName} - Error opening statistic for object {agentGroupName} and filter {agentGroupAndFilter}");
                                    break;
                                default:
                                    Console.WriteLine($"{methodName} - response.Name  : {agentGroupName} and filter {agentGroupAndFilter}");
                                    break;
                            }

[/code]


[/quote]

Getting the Statistic Values is always assyncronous either through Notification or through using the RequestPeekStatistic (note that you cant even use the StatServerProtocol.Request to get it synchronously).

That means that you will always receive the values on the EventInfo as part of the MessageEventArgs on the Method that you set as handler on StatServerProtocol.Received event.


When you use Immediate notification and Insensitivity = 1, you receive an assyncronous EventInfo whenever the statistical value changes.

If you need to do something in your code upon receiving the data, use that handler.

Offline merve.ugursac

  • Newbie
  • *
  • Posts: 11
  • Karma: 0
Thank you so very much for all the information.
Sadly in these circumstances I can't accomplish my task. There had to be some way.

Offline cavagnaro

  • Administrator
  • Hero Member
  • *****
  • Posts: 7639
  • Karma: 56330
The way has actually been explained quite well and clearly from hsujdik. You have 2 ways to do it, it is how it works, async or sync, you need to do your effort there to close the circle.

Offline hsujdik

  • Hero Member
  • *****
  • Posts: 541
  • Karma: 30
Just to correct myself:

There are actually two requests that you can get a current information assynchronously: RequestGetStatistisc and RequestGetStatisticEx

Though, I wouldn't recommend using those in your case since this will open and close statistics on Stat Server each time it is polled.

Offline merve.ugursac

  • Newbie
  • *
  • Posts: 11
  • Karma: 0
I have solved it thanks to your help!
I appreciate your time and effort!