public static Metadata ProcessHeaders(Metadata headers) { if (headers == null) { throw new ArgumentNullException(nameof(headers)); } Metadata.Entry trackingEntry = headers.FirstOrDefault(x => string.CompareOrdinal(x.Key, s_TrackingContextKeyName) == 0); // Retrieve the tracking context from the message header, if it exists. if (trackingEntry != null) { // If an tracking context exists in the message header, always use it to replace the ambient context. TrackingContext tc = TrackingContext.DeSerialize(trackingEntry.ValueBytes); tc.SetAsCurrent(); } else { // If no tracking context exists then create one. TrackingContext.NewCurrentIfEmpty(); Debug.Assert(TrackingContext.Current != null); // Copy the tracking context to the message header. byte[] byteArray = TrackingContext.Serialize(TrackingContext.Current); headers.Add(s_TrackingContextKeyName, byteArray); } return(headers); }
private static void OverwriteTrackingContextHeader( HttpContext httpContext, IList <string> headerKeys, Func <HttpContext, string> headerValueGenerator) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } if (headerKeys == null) { throw new ArgumentNullException(nameof(headerKeys)); } if (headerValueGenerator == null) { throw new ArgumentNullException(nameof(headerValueGenerator)); } TrackingContext currentTrackingContext = TrackingContext.Current; // Replace the http header value in the current Tracking Context, if the // http header exists. if (currentTrackingContext != null) { // Prepare the inputs for the new Tracking Context. Guid callChainId = currentTrackingContext.CallChainId; DateTime originatorUtcTimestamp = currentTrackingContext.OriginatorUtcTimestamp; IDictionary <string, string> extraHeaders = currentTrackingContext .ExtraHeaders .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // Cycle through each of the requested http header keys. foreach (string headerKey in headerKeys) { if (extraHeaders.ContainsKey(headerKey)) { // Overwrite the target http header value. string headerValue = headerValueGenerator(httpContext); extraHeaders[headerKey] = headerValue; } } // Now recreate the current Tracking Context with the overwritten extra headers. var newTrackingContext = new TrackingContext( callChainId, originatorUtcTimestamp, extraHeaders); newTrackingContext.SetAsCurrent(); } }
private static void CreateTrackingContextFromHeaderValues(IEnumerable <string> values) { if (values == null) { throw new ArgumentNullException(nameof(values)); } if (values.Count() > 1) { throw new InvalidOperationException(Properties.Resources.CannotHaveMoreThanOneSerializedTrackingContextInHTTPHeaders); } string tcBase64 = values.FirstOrDefault(); if (string.IsNullOrWhiteSpace(tcBase64)) { TrackingContext.NewCurrentIfEmpty(); } else { // If an tracking context exists in the message header then use it to replace the current context. TrackingContext tc = TrackingContext.DeSerialize(tcBase64.Base64StringToByteArray()); tc.SetAsCurrent(); } }
private static void MergeTrackingContextHeader(HttpContext httpContext) { if (httpContext == null) { throw new ArgumentNullException(nameof(httpContext)); } TrackingContext previousTrackingContext = TrackingContext.Current; // Take the Tracking Context (if it exists) from the http request headers and make it current. TrackingContextHelper.ProcessHttpHeaders(httpContext.Request?.Headers); // Check to see how the new current Tracking Context compares to the previous one. if (previousTrackingContext != null) { TrackingContext currentTrackingContext = TrackingContext.Current; Debug.Assert(currentTrackingContext != null); // Prepare the inputs for the new Tracking Context. Guid callChainId = currentTrackingContext.CallChainId; DateTime originatorUtcTimestamp = currentTrackingContext.OriginatorUtcTimestamp; IDictionary <string, string> extraHeaders = currentTrackingContext .ExtraHeaders .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // Extract the extra headers that were in the previous Tracking Context, but // are not in the inputs for the new Tracking Context. IList <string> nowMissingHeaderNames = previousTrackingContext .ExtraHeaders.Keys .Except(extraHeaders.Keys) .ToList(); // Add the missing extra headers back to the inputs for the new Tracking Context. foreach (string headerName in nowMissingHeaderNames) { extraHeaders.Add(headerName, previousTrackingContext.ExtraHeaders[headerName]); } // Extract the extra headers that were in the previous Tracking Context, and // also in inputs for the new Tracking Context, but whose values are not empty. IList <string> sharedHeaderNames = extraHeaders .Keys .Except(nowMissingHeaderNames) .ToList(); // Add the missing extra header values back to the inputs for the new Tracking Context. foreach (string headerName in sharedHeaderNames) { if (string.IsNullOrWhiteSpace(extraHeaders[headerName])) { extraHeaders[headerName] = previousTrackingContext.ExtraHeaders[headerName]; } } // Now recreate the current Tracking Context with the refilled extra headers. var newTrackingContext = new TrackingContext( callChainId, originatorUtcTimestamp, extraHeaders); newTrackingContext.SetAsCurrent(); } }