In SharePoint 2010 Microsoft introduced a “Correlation Id” that was stamped on an SPRequest object (essentially). This means that for every SharePoint request, there was a unique Guid associated with it that was the correlated with log entries that were also marked with the Guid. This makes it easy to produce an error message in SharePoint, put the correlation Id on it, and then the administrator can quickly pinpoint what happened by searching the logs for the correlation Id instead of sifting through thousands of log entries for the users request.
The problem is that if I were creating a web part in SharePoint that did some work that was fairly long running or had the potential to take a while (for example a web service call to another server to get data), I would not want that to happen during the initial page load. I would rather that the initial page load very quickly, and then have the web part make the request that might take a while via Ajax. This gives the user a more responsive page. However, now we lose the nice correlation Id of the request. The user gets a correlation Id for the initial request of the page, but the subsequent Ajax requests to SharePoint hosted web services that do the long running work get different correlation Id’s even though they are related.
This is not a huge deal, and everything works fine, but for troubleshooting purposes we can do better.
I actually asked this question at a SharePoint Conference in 2011, and was told that it was certainly possible by setting a header, but unfortunately I didn’t have a complete answer as to what exactly that header was. By reflecting the SharePoint code we can get our answer.
This comes from the SPRequestUsageMonitoredScope class constructor that is called early in the SPRequest pipeline. The base class for this object is the SPMonitoredScope class, which defines an Id property as a Guid. This is what your Correlation Id comes from.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | string g; if (httpRequest != null && (g = httpRequest.Headers.Get("SPResponseGuid")) != null) {    try    {       base.Id = new Guid(g);       if (DeveloperDashboard.s_DisplayLevel != SPDeveloperDashboardLevel.Off)       {          ULS.TraceLevelOverrideStart(ULSTraceLevel.VerboseEx);          ULS.SendTraceTag(1701589042u, ULSCat.msoulscat_ULS_Correlation, ULSTraceLevel.VerboseEx, "SPResponseGuid forced correlation switch: {0}", new object[]          {             base.Id          });       }    }    catch (FormatException)    {    }    catch (OverflowException)    {    } } ULS.CorrelationStart(base.Id); |
You can see that it is basically looking for a header with a key of “SPResponseGuid” and if that value is present, it simply takes it and overrides the correlation Id of that request (which is basically just the Id of this SPMonitoredScope derived object).
Now that we know the SharePoint code that can read this header, you just need to set the header when you make an Ajax request in Javascript. That is easy on an XMLHttpRequest object by using the “setRequestHeader” function. In other scenarios, in code, you could set the header in code as well. Anywhere that you are making a subsequent request to SharePoint that is related to the original request is a good place to use the same Correlation Id for troubleshooting purposes.
If you are using jQuery and .ajax, this is very easy.
1 2 3 4 5 6 7 8 9 | var previousRequestGuid = "previous" // some way to get the correlationId of the base page request .ajax({ Â Â Â type: "POST", Â Â Â url: "some web service", Â Â Â data: { name: "Something" }, Â Â Â headers: { "SPResponseGuid", previousRequestGuid } }).done(function(data) { Â Â Â // do something with what we get back }); |
Of course you need some way to get the Correlation Id so it can be sent along to JavaScript so that the Ajax request can consume it. In order to do that I used the code from Wictor Wilén’s blog for getting the proper Correlation Id in code.
1 2 3 4 5 6 7 8 9 10 11 12 13 | [DllImport("advapi32.dll")] private static extern uint EventActivityIdControl(uint controlCode, ref Guid activityId); private const uint EVENT_ACTIVITY_CTRL_GET_ID = 1; public static string CorrelationId {    get    {       Guid g = Guid.Empty;       EventActivityIdControl(EVENT_ACTIVITY_CTRL_GET_ID, ref g);       return g.ToString();    } } |
I put this code in our static logger class so we could get at it. In the code for the page or web part, you would then basically read this correlation Id in code and then send it to the JavaScript layer when you render the page or web part, and then the JavaScript will use it to create the header.
It may not impact the typical end user, but your administrators and tech support (and yourself if you are stuck supporting what you are building) will thank you for making it just a bit easier to track related requests in the SharePoint log.
Recent Comments