05-18-2016 11:03 AM
Is there a way to determine which browsers Agents/Supervisors are using to access Finesse? I need to audit the system for compliance with the supported browsers list.
Recently, when upgrading to UCCX v11, Finesse uses SocketIO and does not work well with older browsers which do not support WebSockets and causes high CPU on the server. I'd like to identify which users might be causing this problem.
Thank you.
Solved! Go to Solution.
05-20-2016 01:03 PM
Hi,
Sorry about the time spent on using the 2.0 gadget. For 11.0, we hosted the finesse.js on the Finesse server and did a re-versioning of the sample gadgets to not be release specific. I will take a note of this and add on the sample gadget page to say that these gadgets are for 11.0 and higher and a link to where to find the older versions. Thank you for the feedback.
The caching on these gadgets are indeed aggressive. I have tried many different things to try to avoid caching (even using the developer tools' no cache mode). I did find a multi-step hack that has been pretty successful. I develop using Firefox, so I use Firebug to debug. When I make a change in my code, I make sure the number of lines is not equal to the previous version (add or delete a log statement). I upload the changed file and click refresh. Then on Firebug, I click the Script tab and go to the javascript file for my gadget. The content of the javascript file will be the latest, but if you look at the line numbers in green, it will not match the breakpoint-able lines. (Make sure you actually do this step of loading the javascript file, because if you don't, this hack won't work) Then click refresh again and it is usually good to go (confirm with the green line numbers). It is a little tedious, but it beats having to restart tomcat.
For your question about HTTP Basic Auth, yes you would need to do that. Which reminds me of a better idea of using the ClientServices's makeRequest API.
The first createNewWebServicesRequest that you have looks correct:
createNewWebServicesRequest : function (handlers) {
clientLogs.log("createNewWebServicesRequest(): in method");
// Build the request's body
var contentBody = {
ClientLog: {
logData : navigator.userAgent
}
};
handlers = handlers || {};
this.myrestRequest("/finesse/api/User/" + finesse.gadget.Config.id + "/ClientLog", {
method: 'POST',
success: handlers.success,
error: handlers.error,
content: contentBody,
});
return this;
},
What I would do in myrestRequest is change:
this.mymakeRequest(encodeURI(url), this._mycreateAjaxHandler(options), params);
to
finesse.clientservices.ClientServices.makeRequest(encodeURI(url), this._mycreateAjaxHandler(options), params);
This will utilize the ClientServices API that has the Basic Auth built in and uses the Finesse credentials of the container. I tried this out on my Finesse 11.0 system and it seems to work.
Then the next step would be to modify the gadget's xml to remove the button and text of the gadget and then move the method call finesse.modules.SampleGadget.makeWebService(); to the onConnect.
As for the finesse is not defined error, did you accidentally remove the first few lines of the javascript file at the top?
var finesse = finesse || {};
finesse.gadget = finesse.gadget || {};
finesse.container = finesse.container || {};
clientLogs = finesse.cslogger.ClientLogger || {}; // for logging
I hope this works for you!
Thanx,
Denise
05-18-2016 11:53 AM
Hi,
Unfortunately, Finesse does not have an automatic way to determine which browsers the Agents/Supervisors are using to access Finesse.
Assuming you are using the Finesse out of the box Agent Desktop, if you have each agent/supervisor click the Send Error Report link at the lower right of the page, it will send the client logs to the Finesse server (in the clientlogs folder). Then, use the administrator CLI to collect the logs: file get activelog desktop recurs compress. This is tedious, but if you look at the first line of each file (where the filename contains the agent's username), you can decipher which type of browser the agent is using.
Here is an example of IE10:
Mozilla/
5.0
(compatible; MSIE
10.0
; Windows NT
6.1
; Trident/
6.0
)
Here is an example of IE11:
Mozilla/
5.0
(Windows NT
6.3
; Trident/
7.0
; rv:
11.0
) like Gecko
05-18-2016
12:15 PM
- last edited on
03-05-2021
10:32 AM
by
dekwan
As an integrator and troubleshooter, I need a way that does not rely on Agent's willingness to participate or understand what is being asked. I would think TAC would want this capability too, because they'll need to validate compliance with browsers when tracking down issues. E.g., IE9 and UCCX 11 with SocketIO; No support for WebSockets causes high CPU.
If there are truly no server logs I can review (E.g., Tomcat), then can you think of a quick Gadget I can embed into the Finesse layout that would collect this data and send it to the Finesse server logs? Perhaps, starting with one of the several sample gadgets?
https://developer.cisco.com/docs/finesse/#!sample-gadgets
Writing to server logs would be best, since then the solution would be self contained.
What do you make of this article showing the user agent header in the logs? Is that for UCCE only?
Finesse Agent Login Trace with the Use of Logs - Cisco
This article talks about turning on those Notifcation Logs, but I don't see those commands in UCCX.
05-19-2016 02:42 PM
I totally understand your concern about having to rely on the Agent's willingness to participate.
Embedding a gadget on the Finesse layout and collecting this data is a great idea! Unfortunately, the Finesse JavaScript Library API doesn't contain the Send Client Logs REST API, so it won't be as simple as using that library. But, you can always call the REST API directly from the gadget.
There isn't an existing gadget to do exactly what you are looking for, but I would suggest using the WebService Sample Gadget 2.0 as a base. This sample gadget fetches the data from an xml and prints it on the gadget. That isn't what you want, but it doesn't have methods to do REST API calls. You would need to change the request from a GET to a POST and also include the request body. For the request body, send just the browser info. Then, in the gadget's xml's onConnect, call the method from your javascript file that calls the client log REST API and the logs will automatically be sent to the Finesse server (of course if the agent reloads or re-logs in, it will send again). Then, after the agents are logged in, there will be a file that contains the browser info that is in the request body for each agent. The filename will contain the agent's username. What you would need to do after all the agents log in is to grab the logs from the finesse server via the administrator cli: file get activelog desktop recurs compress and do a grep for the unsupported browser version using the token information I provided earlier.
I hope this helps! I know this was a lot of steps, but it will get you what you are looking for.
Thanx,
Denise
05-20-2016 07:29 AM
Thanks for that point in the right direction.
I wasted like 8 hours last night messing around with the LearningSampleGadget-2.0 on my UCCX 10.6(1)SU2 system. Turns out, v2.0 samples only work in UCCX 11.x. How do I know? I spun up a dCloud demo for UCCX 11.x and they work there. Also, why do I have to restart Cisco Finesse Tomcat 90% of the time to get new gadget code to render in the browser? It's like the caching on these things is so darn aggressive. Anything I can do to speed up my development cycle? Write code, save, upload, refresh, test, repeat.
Anyway, so now I'm in the UCCX 11.x on dCloud and I'm trying to get this WebService sample app tweaked to upload the ClientLogs, and I'm having some trouble with the following: The ClientLogs API requires the Agent ID ("aholloway" in my case). The WebService sample app doesn't have access (or doesn't appear to) to this information, whereas when I load the LearningSampleGadget it's actually a shown to me with user.getId(). Is there a simple way to get the Agent ID into the WebServices app without all the extra stuff that's in the LearningSampleGadget? E.g., finesse.gadget.Config.id
When I try to use the following modification, the console shows "ReferenceError: finesse is not defined"
createNewWebServicesRequest : function (handlers) {
clientLogs.log("createNewWebServicesRequest(): in method");
var contentBody = {
ClientLog: {
logData: navigator.userAgent
}
};
handlers = handlers || {};
// TODO: change Rest path to match your own web server
this.myrestRequest("/finesse/api/User/" + finesse.gadget.Config.id + "/ClientLog", {
method: 'POST',
success: handlers.success,
error: handlers.error,
content: contentBody,
});
return this;
}
Then, I just hard coded the user ID for one Agent like this, just to see if the basics of calling the REST API was working, however, it was not working and I was still getting a finesse reference error in the console. Do I need to worry about HTTP Basic Auth and how it would need to be addressed or is that implicit in some underlying code, and the Agent's creds will automatically be passed with the make request?
createNewWebServicesRequest : function (handlers) {
clientLogs.log("createNewWebServicesRequest(): in method");
var contentBody = {
ClientLog: {
logData: navigator.userAgent
}
};
handlers = handlers || {};
// TODO: change Rest path to match your own web server
this.myrestRequest("/finesse/api/User/aholloway/ClientLog", {
method: 'POST',
success: handlers.success,
error: handlers.error,
content: contentBody,
});
return this;
}
I should mention that I did also update the host the sample is pointing at:
mymakeRequest : function (url, handler, params) {
clientLogs.log("mymakeRequest(): in method");
params = params || {};
params[gadgets.io.RequestParameters.HEADERS] = params[gadgets.io.RequestParameters.HEADERS] || {};
// This is the url we want to get to:
// http://10.88.194.158:8080/userContent/HelloWorld.html
// TODO: Change the IP address to your server
gadgets.io.makeRequest(encodeURI("https://uccx1.dcloud.cisco.com:8445") + url, handler, params);
clientLogs.log("mymakeRequest(): io.makeRequest to https://uccx1.dcloud.cisco.com:8445" + url);
}
I should mention that I did get the WebService Sample app to run successfully, when pointing the URL at an off box Web Server like so:
createNewWebServicesRequest : function (handlers) {
clientLogs.log("createNewWebServicesRequest(): in method");
var contentBody = {};
handlers = handlers || {};
// TODO: change Rest path to match your own web server
this.myrestRequest("/finesse/HelloWorld.xml", {
method: 'GET',
success: handlers.success,
error: handlers.error,
content: contentBody,
});
return this;
}
mymakeRequest : function (url, handler, params) {
clientLogs.log("mymakeRequest(): in method");
params = params || {};
params[gadgets.io.RequestParameters.HEADERS] = params[gadgets.io.RequestParameters.HEADERS] || {};
// This is the url we want to get to:
// http://10.88.194.158:8080/userContent/HelloWorld.html
// TODO: Change the IP address to your server
gadgets.io.makeRequest(encodeURI("http://ad1.dcloud.cisco.com") + url, handler, params);
clientLogs.log("mymakeRequest(): io.makeRequest to http://ad1.dcloud.cisco.com" + url);
}
But if I switch it to even just this, it fails with "finesse is not defined" in the web console.
createNewWebServicesRequest : function (handlers) {
clientLogs.log("createNewWebServicesRequest(): in method");
var contentBody = {};
handlers = handlers || {};
// TODO: change Rest path to match your own web server
this.myrestRequest("/finesse/api/SystemInfo", {
method: 'GET',
success: handlers.success,
error: handlers.error,
content: contentBody,
});
return this;
}
mymakeRequest : function (url, handler, params) {
clientLogs.log("mymakeRequest(): in method");
params = params || {};
params[gadgets.io.RequestParameters.HEADERS] = params[gadgets.io.RequestParameters.HEADERS] || {};
// This is the url we want to get to:
// http://10.88.194.158:8080/userContent/HelloWorld.html
// TODO: Change the IP address to your server
gadgets.io.makeRequest(encodeURI("http://uccx1.dcloud.cisco.com:8082") + url, handler, params);
clientLogs.log("mymakeRequest(): io.makeRequest to http://uccx1.dcloud.cisco.com:8082" + url);
}
05-20-2016 01:03 PM
Hi,
Sorry about the time spent on using the 2.0 gadget. For 11.0, we hosted the finesse.js on the Finesse server and did a re-versioning of the sample gadgets to not be release specific. I will take a note of this and add on the sample gadget page to say that these gadgets are for 11.0 and higher and a link to where to find the older versions. Thank you for the feedback.
The caching on these gadgets are indeed aggressive. I have tried many different things to try to avoid caching (even using the developer tools' no cache mode). I did find a multi-step hack that has been pretty successful. I develop using Firefox, so I use Firebug to debug. When I make a change in my code, I make sure the number of lines is not equal to the previous version (add or delete a log statement). I upload the changed file and click refresh. Then on Firebug, I click the Script tab and go to the javascript file for my gadget. The content of the javascript file will be the latest, but if you look at the line numbers in green, it will not match the breakpoint-able lines. (Make sure you actually do this step of loading the javascript file, because if you don't, this hack won't work) Then click refresh again and it is usually good to go (confirm with the green line numbers). It is a little tedious, but it beats having to restart tomcat.
For your question about HTTP Basic Auth, yes you would need to do that. Which reminds me of a better idea of using the ClientServices's makeRequest API.
The first createNewWebServicesRequest that you have looks correct:
createNewWebServicesRequest : function (handlers) {
clientLogs.log("createNewWebServicesRequest(): in method");
// Build the request's body
var contentBody = {
ClientLog: {
logData : navigator.userAgent
}
};
handlers = handlers || {};
this.myrestRequest("/finesse/api/User/" + finesse.gadget.Config.id + "/ClientLog", {
method: 'POST',
success: handlers.success,
error: handlers.error,
content: contentBody,
});
return this;
},
What I would do in myrestRequest is change:
this.mymakeRequest(encodeURI(url), this._mycreateAjaxHandler(options), params);
to
finesse.clientservices.ClientServices.makeRequest(encodeURI(url), this._mycreateAjaxHandler(options), params);
This will utilize the ClientServices API that has the Basic Auth built in and uses the Finesse credentials of the container. I tried this out on my Finesse 11.0 system and it seems to work.
Then the next step would be to modify the gadget's xml to remove the button and text of the gadget and then move the method call finesse.modules.SampleGadget.makeWebService(); to the onConnect.
As for the finesse is not defined error, did you accidentally remove the first few lines of the javascript file at the top?
var finesse = finesse || {};
finesse.gadget = finesse.gadget || {};
finesse.container = finesse.container || {};
clientLogs = finesse.cslogger.ClientLogger || {}; // for logging
I hope this works for you!
Thanx,
Denise
05-23-2016 12:26 PM
I get so happy when I see your reply hit my email inbox. Thank you for helping.
Working backwards in the replies...
No, I did not delete the lines at the top. In fact, if I simply change the host from ad1.dcloud.cisco.com to uccx1.dcloud.cisco.com:8082, that is enough to break it. So, my question would then be: "Is there some restriction or limitation on a Finesse Gadget making a call to itself? I.e., Using FQDN vs IP vs localhost? HTTP vs HTTPS? Something else?
I would love to see what you're doing in Firebug, because: A) I didn't understand what you explained, and B) I think it would save my sanity, as opposed to waiting and restarting services that take 10 minutes to return (at least in dCloud they do). Could you post screenshots, or a screencast of your development process?
05-24-2016 03:24 PM
If the gadget is being hosted on the Finesse server, you just need to use localhost. You need to make sure the url is accessible from the Finesse server itself.
Let me try to explain my development hack in text and screenshots:
1) My gadget's JS file is called WebService.js
2) WebService.js file on a text editor is 244 lines.
3) With the gadget loaded on the Finesse UI, I open Firebug and go to the Script tab.
4) In the area that starts contact?container..., click that and type in WebService.js (it will filter the list of script files).
5) Select the file that ends in WebService.js.
6) Scroll down and notice that the green line numbers match the javascript's lines.
7) I make my changes to WebService.js
8) If the number of lines of WebService.js is still 244, then I add a log statement to make the number of lines 245 (or more).
9) I upload the WebService.js file to the Finesse server.
10) I click Refresh to reload the Finesse desktop.
11) I go back to Firebug's Script Tab and go to the WebService.js just like earlier.
12) Notice how the line number is not green where I added the log statement?
13) The lines after this added line are also incorrect in terms of being marked green.
14) This is how I know that the WebService.js file is cached.
15) Refresh the page again.
16) Go back to the WebService.js on the Script tab and the green line numbers should match the javascript lines.
17) This is how I know that the WebService.js is using the latest version.
Make sure you actually go to the script tab and the WebService.js file in step 12. If you don't and just refresh the page twice, it will continue to be cached. I think Firebug needs to load the file and the green lines to realize that it is cached.
I know this is tedious, but it is way faster than restarting tomcat. I hope this improves the speed of your development.
Thanx,
Denise
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide