コード例 #1
0
        public void InitializerDoesNotFailOnNullContextStore()
        {
            var telemetry = new DependencyTelemetry();

            CallContextHelpers.SaveOperationContext(null);
            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);
            Assert.IsNull(telemetry.Context.Operation.ParentId);
        }
コード例 #2
0
        public void TelemetryContextIsUpdatedWithOperationNameForDependencyTelemetry()
        {
            CallContextHelpers.SaveOperationContext(new OperationContextForCallContext {
                RootOperationName = "OperationName"
            });
            var telemetry = new DependencyTelemetry();

            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);
            Assert.AreEqual(telemetry.Context.Operation.Name, "OperationName");
            CallContextHelpers.RestoreOperationContext(null);
        }
コード例 #3
0
        public void TelemetryContextIsUpdatedWithOperationIdForDependencyTelemetry()
        {
            CallContextHelpers.SaveOperationContext(new OperationContextForCallContext {
                ParentOperationId = "ParentOperationId"
            });
            var telemetry = new DependencyTelemetry();

            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);
            Assert.AreEqual("ParentOperationId", telemetry.Context.Operation.ParentId);
            CallContextHelpers.RestoreOperationContext(null);
        }
コード例 #4
0
        public void InitializeDoesNotUpdateOperationNameIfItExists()
        {
            CallContextHelpers.SaveOperationContext(new OperationContextForCallContext {
                RootOperationName = "OperationName"
            });
            var telemetry = new DependencyTelemetry();

            telemetry.Context.Operation.Name = "OldOperationName";
            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);
            Assert.AreEqual(telemetry.Context.Operation.Name, "OldOperationName");
            CallContextHelpers.RestoreOperationContext(null);
        }
コード例 #5
0
        public void InitializeDoesNotUpdateOperationIdIfItExists()
        {
            CallContextHelpers.SaveOperationContext(new OperationContextForCallContext {
                ParentOperationId = "ParentOperationId"
            });
            var telemetry = new DependencyTelemetry();

            telemetry.Context.Operation.ParentId = "OldParentOperationId";
            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);
            Assert.AreEqual("OldParentOperationId", telemetry.Context.Operation.ParentId);
            CallContextHelpers.RestoreOperationContext(null);
        }
コード例 #6
0
        public static bool UpdateOperationName(string operationName)
        {
            var context = CallContextHelpers.GetCurrentOperationContext();

            if (context == null)
            {
                return(false);
            }

            context.RootOperationName = operationName;
            CallContextHelpers.SaveOperationContext(context);
            return(true);
        }
        public void TestInitialize()
        {
            var configuration = new TelemetryConfiguration();

            this.sendItems = new List <ITelemetry>();
            configuration.TelemetryChannel = new StubTelemetryChannel {
                OnSend = item => this.sendItems.Add(item)
            };
            configuration.InstrumentationKey = Guid.NewGuid().ToString();
            configuration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
            this.telemetryClient = new TelemetryClient(configuration);
            CallContextHelpers.SaveOperationContext(null);
        }
コード例 #8
0
        /// <summary>
        /// Creates an operation object with a given telemetry item.
        /// </summary>
        /// <typeparam name="T">Type of the telemetry item.</typeparam>
        /// <param name="telemetryClient">Telemetry client object.</param>
        /// <param name="operationTelemetry">Operation to start.</param>
        /// <returns>Operation item object with a new telemetry item having current start time and timestamp.</returns>
        public static IOperationHolder <T> StartOperation <T>(this TelemetryClient telemetryClient, T operationTelemetry) where T : OperationTelemetry
        {
            if (telemetryClient == null)
            {
                throw new ArgumentNullException("Telemetry client cannot be null.");
            }

            if (operationTelemetry == null)
            {
                throw new ArgumentNullException("operationTelemetry cannot be null.");
            }

            var operationHolder = new CallContextBasedOperationHolder <T>(telemetryClient, operationTelemetry)
            {
                // Parent context store is assigned to operation that is used to restore call context.
                ParentContext = CallContextHelpers.GetCurrentOperationContext()
            };

            telemetryClient.Initialize(operationTelemetry);

            // Initialize operation id if it wasn't initialized by telemetry initializers
            if (string.IsNullOrEmpty(operationTelemetry.Id))
            {
                operationTelemetry.GenerateOperationId();
            }

            // If the operation is not executing in the context of any other operation
            // set its name and id as a context (root) operation name and id
            if (string.IsNullOrEmpty(operationTelemetry.Context.Operation.Id))
            {
                operationTelemetry.Context.Operation.Id = operationTelemetry.Id;
            }

            if (string.IsNullOrEmpty(operationTelemetry.Context.Operation.Name))
            {
                operationTelemetry.Context.Operation.Name = operationTelemetry.Name;
            }

            operationTelemetry.Start();

            // Update the call context to store certain fields that can be used for subsequent operations.
            var operationContext = new OperationContextForCallContext();

            operationContext.ParentOperationId = operationTelemetry.Id;
            operationContext.RootOperationId   = operationTelemetry.Context.Operation.Id;
            operationContext.RootOperationName = operationTelemetry.Context.Operation.Name;
            CallContextHelpers.SaveOperationContext(operationContext);

            return(operationHolder);
        }
コード例 #9
0
        public void InitializeWithCorrelationContextSetsProperties()
        {
            CallContextHelpers.SaveOperationContext(new OperationContextForCallContext
            {
                CorrelationContext = new Dictionary <string, string> {
                    ["k1"] = "v1", ["k2"] = "v2"
                }
            });

            var telemetry = new DependencyTelemetry();

            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);

            Assert.AreEqual(2, telemetry.Context.Properties.Count);
            Assert.AreEqual("v1", telemetry.Context.Properties["k1"]);
            Assert.AreEqual("v2", telemetry.Context.Properties["k2"]);
            CallContextHelpers.RestoreOperationContext(null);
        }
コード例 #10
0
        public static bool SetOperationContext(RequestTelemetry requestTelemetry, IDictionary <string, string> correlationContext)
        {
            var context = CallContextHelpers.GetCurrentOperationContext();

            if (context != null)
            {
                return(false);
            }

            context = new OperationContextForCallContext()
            {
                ParentOperationId  = requestTelemetry.Id,
                RootOperationId    = requestTelemetry.Context.Operation.Id,
                RootOperationName  = requestTelemetry.Context.Operation.Name,
                CorrelationContext = correlationContext
            };

            CallContextHelpers.SaveOperationContext(context);
            return(true);
        }
コード例 #11
0
        public void InitializeWithActivityWinsOverCallContext()
        {
            CallContextHelpers.SaveOperationContext(new OperationContextForCallContext {
                RootOperationId = "callContextRoot"
            });
            var currentActivity = new Activity("test");

            currentActivity.AddTag("OperationName", "operation");
            currentActivity.AddBaggage("k1", "v1");
            currentActivity.Start();
            var telemetry = new RequestTelemetry();

            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);

            Assert.AreEqual(currentActivity.TraceId.ToHexString(), telemetry.Context.Operation.Id);
            Assert.AreEqual(W3CUtilities.FormatTelemetryId(currentActivity.TraceId.ToHexString(), currentActivity.SpanId.ToHexString()), telemetry.Context.Operation.ParentId);

            Assert.AreEqual("operation", telemetry.Context.Operation.Name);
            Assert.AreEqual(1, telemetry.Properties.Count);
            Assert.AreEqual("v1", telemetry.Properties["k1"]);
            currentActivity.Stop();
        }
        public void InitilaizeWithActivityWinsOverCallContext()
        {
            CallContextHelpers.SaveOperationContext(new OperationContextForCallContext {
                RootOperationId = "callContextRoot"
            });
            var currentActivity = new Activity("test");

            currentActivity.SetParentId("activityRoot");
            currentActivity.AddTag("OperationName", "operation");
            currentActivity.AddBaggage("k1", "v1");
            currentActivity.Start();
            var telemetry = new RequestTelemetry();

            (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry);

            Assert.AreEqual("activityRoot", telemetry.Context.Operation.Id);
            Assert.AreEqual(currentActivity.Id, telemetry.Context.Operation.ParentId);
            Assert.IsTrue(telemetry.Context.Operation.ParentId.StartsWith("|activityRoot."));

            Assert.AreEqual("operation", telemetry.Context.Operation.Name);
            Assert.AreEqual(1, telemetry.Context.Properties.Count);
            Assert.AreEqual("v1", telemetry.Context.Properties["k1"]);
            currentActivity.Stop();
        }
コード例 #13
0
        /// <summary>
        /// Creates an operation object with a given telemetry item.
        /// </summary>
        /// <typeparam name="T">Type of the telemetry item.</typeparam>
        /// <param name="telemetryClient">Telemetry client object.</param>
        /// <param name="operationTelemetry">Operation to start.</param>
        /// <returns>Operation item object with a new telemetry item having current start time and timestamp.</returns>
        public static IOperationHolder <T> StartOperation <T>(this TelemetryClient telemetryClient, T operationTelemetry) where T : OperationTelemetry
        {
            if (telemetryClient == null)
            {
                throw new ArgumentNullException("Telemetry client cannot be null.");
            }

            if (operationTelemetry == null)
            {
                throw new ArgumentNullException("operationTelemetry cannot be null.");
            }

            telemetryClient.Initialize(operationTelemetry);

            var telemetryContext = operationTelemetry.Context.Operation;

            // Initialize operation id if it wasn't initialized by telemetry initializers
            if (string.IsNullOrEmpty(operationTelemetry.Id))
            {
                operationTelemetry.GenerateOperationId();
            }

            // If the operation is not executing in the context of any other operation
            // set its name and id as a context (root) operation name and id
            if (string.IsNullOrEmpty(telemetryContext.Id))
            {
                telemetryContext.Id = operationTelemetry.Id;
            }

            if (string.IsNullOrEmpty(telemetryContext.Name))
            {
                telemetryContext.Name = operationTelemetry.Name;
            }

            bool isActivityAvailable = false;

            isActivityAvailable = ActivityExtensions.TryRun(() =>
            {
                var parentActivity    = Activity.Current;
                var operationActivity = new Activity(ChildActivityName);

                string operationName = telemetryContext.Name;
                if (string.IsNullOrEmpty(operationName))
                {
                    operationName = parentActivity?.GetOperationName();
                }

                if (!string.IsNullOrEmpty(operationName))
                {
                    operationActivity.SetOperationName(operationName);
                }

                if (parentActivity == null)
                {
                    // telemetryContext.Id is always set: if it was null, it is set to opTelemetry.Id and opTelemetry.Id is never null
                    operationActivity.SetParentId(telemetryContext.Id);
                }

                operationActivity.Start();
                operationTelemetry.Id = operationActivity.Id;
            });

            var operationHolder = new OperationHolder <T>(telemetryClient, operationTelemetry);

            if (!isActivityAvailable)
            {
                // Parent context store is assigned to operation that is used to restore call context.
                operationHolder.ParentContext = CallContextHelpers.GetCurrentOperationContext();
            }

            operationTelemetry.Start();

            if (!isActivityAvailable)
            {
                // Update the call context to store certain fields that can be used for subsequent operations.
                var operationContext = new OperationContextForCallContext
                {
                    ParentOperationId = operationTelemetry.Id,
                    RootOperationId   = operationTelemetry.Context.Operation.Id,
                    RootOperationName = operationTelemetry.Context.Operation.Name
                };
                CallContextHelpers.SaveOperationContext(operationContext);
            }

            return(operationHolder);
        }
コード例 #14
0
 public static void CleanOperationContext()
 {
     CallContextHelpers.SaveOperationContext(null);
 }
コード例 #15
0
        /// <summary>
        /// Creates an operation object with a given telemetry item. 
        /// </summary>
        /// <typeparam name="T">Type of the telemetry item.</typeparam>
        /// <param name="telemetryClient">Telemetry client object.</param>
        /// <param name="operationTelemetry">Operation to start.</param>
        /// <returns>Operation item object with a new telemetry item having current start time and timestamp.</returns>
        public static IOperationHolder<T> StartOperation<T>(this TelemetryClient telemetryClient, T operationTelemetry) where T : OperationTelemetry
        {
            if (telemetryClient == null)
            {
                throw new ArgumentNullException(nameof(telemetryClient));
            }

            if (operationTelemetry == null)
            {
                throw new ArgumentNullException(nameof(operationTelemetry));
            }

            // We initialize telemetry here AND in Track method because of RichPayloadEventSource.
            // It sends Start and Stop events for OperationTelemetry. During Start event telemetry
            // has to contain essential telemetry properties such as correlations ids and ikey.
            // Also, examples in our documentation rely on the fact that correlation Ids are set
            // after StartOperation call and before operation is stopped.
            // Before removing this call (for optimization), make sure:
            // 1) correlation ids are set before method leaves
            // 2) RichPayloadEventSource is re-factored to work without ikey in Start event (or ikey is set)
            //    and does not require other properties in telemetry
            telemetryClient.Initialize(operationTelemetry);

            var telemetryContext = operationTelemetry.Context.Operation;

            // Initialize operation id if it wasn't initialized by telemetry initializers
            if (string.IsNullOrEmpty(operationTelemetry.Id))
            {
                operationTelemetry.GenerateOperationId();
            }

            // If the operation is not executing in the context of any other operation
            // set its name and id as a context (root) operation name and id
            if (string.IsNullOrEmpty(telemetryContext.Id))
            {
                telemetryContext.Id = operationTelemetry.Id;
            }

            if (string.IsNullOrEmpty(telemetryContext.Name))
            {
                telemetryContext.Name = operationTelemetry.Name;
            }

            bool isActivityAvailable = false;

            isActivityAvailable = ActivityExtensions.TryRun(() =>
            {
                var parentActivity = Activity.Current;
                var operationActivity = new Activity(ChildActivityName);

                string operationName = telemetryContext.Name;
                if (string.IsNullOrEmpty(operationName))
                {
                    operationName = parentActivity?.GetOperationName();
                }

                if (!string.IsNullOrEmpty(operationName))
                {
                    operationActivity.SetOperationName(operationName);
                }

                if (parentActivity == null)
                {
                    // telemetryContext.Id is always set: if it was null, it is set to opTelemetry.Id and opTelemetry.Id is never null
                    operationActivity.SetParentId(telemetryContext.Id);
                }

                operationActivity.Start();
                operationTelemetry.Id = operationActivity.Id;
            });

            var operationHolder = new OperationHolder<T>(telemetryClient, operationTelemetry);
            if (!isActivityAvailable)
            {
                // Parent context store is assigned to operation that is used to restore call context.
                operationHolder.ParentContext = CallContextHelpers.GetCurrentOperationContext();
            }

            operationTelemetry.Start();

            if (!isActivityAvailable)
            {
                // Update the call context to store certain fields that can be used for subsequent operations.
                var operationContext = new OperationContextForCallContext
                {
                    ParentOperationId = operationTelemetry.Id,
                    RootOperationId = operationTelemetry.Context.Operation.Id,
                    RootOperationName = operationTelemetry.Context.Operation.Name
                };
                CallContextHelpers.SaveOperationContext(operationContext);
            }

            return operationHolder;
        }
コード例 #16
0
        /// <summary>
        /// Creates an operation object with a given telemetry item.
        /// </summary>
        /// <typeparam name="T">Type of the telemetry item.</typeparam>
        /// <param name="telemetryClient">Telemetry client object.</param>
        /// <param name="operationTelemetry">Operation to start.</param>
        /// <returns>Operation item object with a new telemetry item having current start time and timestamp.</returns>
        public static IOperationHolder <T> StartOperation <T>(this TelemetryClient telemetryClient, T operationTelemetry) where T : OperationTelemetry
        {
            if (telemetryClient == null)
            {
                throw new ArgumentNullException(nameof(telemetryClient));
            }

            if (operationTelemetry == null)
            {
                throw new ArgumentNullException(nameof(operationTelemetry));
            }

            var  telemetryContext  = operationTelemetry.Context.Operation;
            bool idsAssignedByUser = !string.IsNullOrEmpty(telemetryContext.Id);

            // We initialize telemetry here AND in Track method because of RichPayloadEventSource.
            // It sends Start and Stop events for OperationTelemetry. During Start event telemetry
            // has to contain essential telemetry properties such as correlations ids and ikey.
            // Also, examples in our documentation rely on the fact that correlation Ids are set
            // after StartOperation call and before operation is stopped.
            // Before removing this call (for optimization), make sure:
            // 1) correlation ids are set before method leaves
            // 2) RichPayloadEventSource is re-factored to work without ikey in Start event (or ikey is set)
            //    and does not require other properties in telemetry
            telemetryClient.Initialize(operationTelemetry);

            // Initialize operation id if it wasn't initialized by telemetry initializers
            if (string.IsNullOrEmpty(operationTelemetry.Id))
            {
                operationTelemetry.GenerateOperationId();
            }

            // If the operation is not executing in the context of any other operation
            // set its name as a context (root) operation name.
            if (string.IsNullOrEmpty(telemetryContext.Name))
            {
                telemetryContext.Name = operationTelemetry.Name;
            }

            OperationHolder <T> operationHolder = null;

            var isActivityAvailable = ActivityExtensions.TryRun(() =>
            {
                var parentActivity    = Activity.Current;
                var operationActivity = new Activity(ChildActivityName);

                string operationName = telemetryContext.Name;
                if (string.IsNullOrEmpty(operationName))
                {
                    operationName = parentActivity?.GetOperationName();
                }

                if (!string.IsNullOrEmpty(operationName))
                {
                    operationActivity.SetOperationName(operationName);
                }

                if (idsAssignedByUser)
                {
                    if (Activity.DefaultIdFormat == ActivityIdFormat.W3C)
                    {
                        if (W3CUtilities.IsCompatibleW3CTraceId(telemetryContext.Id))
                        {
                            // If the user provided operationId is W3C Compatible, use it.
                            operationActivity.SetParentId(ActivityTraceId.CreateFromString(telemetryContext.Id.AsSpan()),
                                                          default(ActivitySpanId), ActivityTraceFlags.None);
                        }
                        else
                        {
                            // If user provided operationId is not W3C compatible, generate a new one instead.
                            // and store supplied value inside custom property.
                            operationTelemetry.Properties.Add(W3CConstants.LegacyRootIdProperty, telemetryContext.Id);
                            telemetryContext.Id = null;
                        }
                    }
                    else
                    {
                        operationActivity.SetParentId(telemetryContext.Id);
                    }
                }

                operationActivity.Start();

                if (operationActivity.IdFormat == ActivityIdFormat.W3C)
                {
                    if (string.IsNullOrEmpty(telemetryContext.Id))
                    {
                        telemetryContext.Id = operationActivity.TraceId.ToHexString();
                    }

                    // ID takes the form |TraceID.SpanId.
                    // TelemetryContext.Id used instead of TraceID.ToHexString() for perf.
                    operationTelemetry.Id = W3CUtilities.FormatTelemetryId(telemetryContext.Id, operationActivity.SpanId.ToHexString());
                }
                else
                {
                    if (string.IsNullOrEmpty(telemetryContext.Id))
                    {
                        telemetryContext.Id = operationActivity.RootId;
                    }

                    operationTelemetry.Id = operationActivity.Id;
                }

                operationHolder = new OperationHolder <T>(telemetryClient, operationTelemetry, parentActivity == operationActivity.Parent ? null : parentActivity);
            });

            if (!isActivityAvailable)
            {
                // Parent context store is assigned to operation that is used to restore call context.
                operationHolder = new OperationHolder <T>(telemetryClient, operationTelemetry)
                {
                    ParentContext = CallContextHelpers.GetCurrentOperationContext(),
                };
                telemetryContext.Id = operationTelemetry.Id;
            }

            operationTelemetry.Start();

            if (!isActivityAvailable)
            {
                // Update the call context to store certain fields that can be used for subsequent operations.
                var operationContext = new OperationContextForCallContext
                {
                    ParentOperationId = operationTelemetry.Id,
                    RootOperationId   = operationTelemetry.Context.Operation.Id,
                    RootOperationName = operationTelemetry.Context.Operation.Name,
                };
                CallContextHelpers.SaveOperationContext(operationContext);
            }

            return(operationHolder);
        }