/// <summary> /// Start operation creates an operation object with a respective telemetry item. /// </summary> /// <typeparam name="T">Type of the telemetry item.</typeparam> /// <param name="telemetryClient">Telemetry client object.</param> /// <param name="operationName">Name of the operation that customer is planning to propagate.</param> /// <param name="operationId">Operation ID to set in the new operation.</param> /// <param name="parentOperationId">Optional parent operation ID to set in the new operation.</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, string operationName, string operationId, string parentOperationId = null) where T : OperationTelemetry, new() { if (telemetryClient == null) { throw new ArgumentNullException(nameof(telemetryClient)); } var operationTelemetry = new T(); if (string.IsNullOrEmpty(operationTelemetry.Name) && !string.IsNullOrEmpty(operationName)) { operationTelemetry.Name = operationName; } if (string.IsNullOrEmpty(operationTelemetry.Context.Operation.Id) && !string.IsNullOrEmpty(operationId)) { var isActivityAvailable = ActivityExtensions.TryRun(() => { if (Activity.DefaultIdFormat == ActivityIdFormat.W3C) { if (W3CUtilities.IsCompatibleW3CTraceId(operationId)) { // If the user provided operationid is W3C Compatible, use it. operationTelemetry.Context.Operation.Id = operationId; } else { // If user provided operationid is not W3C compatible, generate a new one instead. // and store supplied value inside customproperty. operationTelemetry.Context.Operation.Id = ActivityTraceId.CreateRandom().ToHexString(); operationTelemetry.Properties.Add(W3CConstants.LegacyRootIdProperty, operationId); } } else { operationTelemetry.Context.Operation.Id = operationId; } }); if (!isActivityAvailable) { operationTelemetry.Context.Operation.Id = operationId; } } if (string.IsNullOrEmpty(operationTelemetry.Context.Operation.ParentId) && !string.IsNullOrEmpty(parentOperationId)) { operationTelemetry.Context.Operation.ParentId = parentOperationId; } return(StartOperation(telemetryClient, operationTelemetry)); }
/// <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); }
/// <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; }
public void CanLoadDiagnosticSourceAssembly() { Assert.IsTrue(ActivityExtensions.TryRun(() => Assert.IsNull(Activity.Current))); }
/// <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); }