“It is not the critic who counts; not the man who points out how the strong man stumbles, or where the doer of deeds could have done them better. The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood; who strives valiantly; who errs, who comes short again and again, because there is no effort without error and shortcoming; but who does actually strive to do the deeds; who knows great enthusiasms, the great devotions; who spends himself in a worthy cause; who at the best knows in the end the triumph of high achievement, and who at the worst, if he fails, at least fails while daring greatly, so that his place shall never be with those cold and timid souls who neither know victory nor defeat.”
— Theodore Roosevelt
Now that we have added the code to log all of our potential Events, we need to test that code out to make sure that it actually works. The only way to do that is for something to happen to trigger the logging of the Event. Some errors are easier to produce than others, so we might as well start out with an easy one first.
Probably the easiest of all, particularly since we have already done this in our earlier testing, is to force an invalid HTTP Response Code. We accomplished that when we were testing our Outbound REST Message by having the wrong credentials for the service. That got us a 401 response code instead of the desired 200. Since we are storing our credential values in System Properties, all we need to do in order to force a 401 response code is to change the value of one or both of those properties. Let’s do that now.
Now all that we need to do is make an address change on some User Profile and see what happens. Since our approach to service failures was to allow the update to proceed without address validation, you won’t really see anything when you update the user’s record. To find out if an Event was actually generated from the issue, we will have to take a peek at the Events table. The easiest way to do that is to select the All Events option from the left-hand navigation. Sure enough, our new Event is now sitting out there. Let’s take a look.
Everything looks to be in order, and thanks to the Event logging utility that we were able to leverage, there is data populated in the Event that we did not have to pass in ourselves. The JSON data in the Additional Info field is a little hard to read, but we have already gone over a quick fix for that. We should go ahead and do that same thing here.
That’s much better.
One other thing that you may have noticed is that logging this Event generated an Alert. Let’s take a look at the Alert now by clicking on the little info icon on the right side of the Alert field and then clicking on the Open Record button in the pop-up window.
One of the things that you may have noticed is that ServiceNow generated a Message Key for our Event by combining a number of other Event properties. The generated message key for this Event is:
AddressValidationUtils_ServiceNow_ServiceNow_alene.rabeck_Invalid Response Code
If you do not supply a Message Key of your own, then one will be generated for you by combining the Source, Node, Type, Resource, and Metric Name. ServiceNow collects all Events with the same Message Key under a single Alert. This prevents multiple actions from being initiated for the same issue. For example, if a user attempted to update the profile of the same User multiple times, an Event would be logged for every failed attempt to reach the address validation service. However, all of those Events would be associated with a single Alert, so only one remediation action would be invoked. On the other hand, if an update was attempted for a different User, any Events logged as a result of that activity would be consolidated under a different Alert, as the Resource (the User, in our example) would be different, which would generate a different Message Key.
Another thing that you may have noticed is that there is no Task associated with this Alert. Tasks can be generated from Alerts using Alert Management Rules, but there are currently no rules in place that apply to this Alert, so no further action was taken. Before we are through with this exercise, we will be building a rule to spawn Incidents from our Alerts, but that’s not today’s concern. Today I want to focus on the testing of our Events.
We added code to our Script Include to log 4 different kinds of Events, and so far, we have only tested one of those, the invalid HTTP Response Code. The other three all have something to do with the response content returned from the service, which makes it a little more difficult to test, since we have no control over the response returned from the service. To test these other three, we will we need to add some temporary code to alter the response that comes back from the service to something that will trigger each of our other Events. We can add that code right after we get the actual response from the service and then alter it to force an error for testing purposes. Here is the original line of code that grabs the response content along with our alterations to produce an error condition:
var body = resp.getBody();
// temporary test code (remove after testing)
body = '[';
// end temporary test code
That value should trigger the unparsable response error. Now, all we need to do to test it is to issue an address change and then check the Events table for the resulting Event. To trigger the invalid response content error, you can change the inserted line to this:
body = '[]';
Now the response is parsable, but it is empty, which should take us to our third error condition. To get to the fourth, we can alter it again to this:
body = '[{}]';
Now the response is parsable and the array contains a single element, so that should get us past the earlier two issues. Since the object does not have an analysis property, though, that should drop us into our fourth error condition, which should log yet a different Event.
Once you complete all of your testing, you will want to go back into the code and remove all of the lines we added for testing purposes, and then test one more time, just to make sure that everything is now back working as it should. With that out of the way, we have now completed the testing for all of our recent changes.
Now that we are successfully logging all of these Events, we are going to want to do something with them. That process deserves an installment devoted exclusively to that effort, so we will leave that exercise for our next time out.