Пример #1
0
        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);
        }
Пример #2
0
        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();
            }
        }
Пример #3
0
        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();
            }
        }
Пример #4
0
        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();
            }
        }