public void InitializerDoesNotFailOnNullContextStore() { var telemetry = new DependencyTelemetry(); CallContextHelpers.SaveOperationContext(null); (new OperationCorrelationTelemetryInitializer()).Initialize(telemetry); Assert.IsNull(telemetry.Context.Operation.ParentId); }
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); }
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); }
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); }
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); }
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); }
/// <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); }
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); }
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); }
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(); }
/// <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); }
public static void CleanOperationContext() { CallContextHelpers.SaveOperationContext(null); }
/// <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; }
/// <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); }