public static Activity StartActivity(string name, string displayName = null, IEnumerable <KeyValuePair <string, object> > tags = null) { var activity = _activitySource.CreateActivity(name, ActivityKind.Internal, default(ActivityContext), tags: tags); if (activity != null && !string.IsNullOrEmpty(displayName)) { activity.DisplayName = displayName; } return(activity?.Start()); }
private Activity?StartActivity(HttpContext httpContext, bool loggingEnabled, bool diagnosticListenerActivityCreationEnabled, out bool hasDiagnosticListener) { var activity = _activitySource.CreateActivity(ActivityName, ActivityKind.Server); if (activity is null && (loggingEnabled || diagnosticListenerActivityCreationEnabled)) { activity = new Activity(ActivityName); } hasDiagnosticListener = false; if (activity is null) { return(null); } var headers = httpContext.Request.Headers; _propagator.ExtractTraceIdAndState(headers,
private static Activity?CreateActivity(HttpRequestMessage requestMessage) { Activity?activity = null; if (s_activitySource.HasListeners()) { activity = s_activitySource.CreateActivity(DiagnosticsHandlerLoggingStrings.ActivityName, ActivityKind.Client); } if (activity is null) { if (Activity.Current is not null || s_diagnosticListener.IsEnabled(DiagnosticsHandlerLoggingStrings.ActivityName, requestMessage)) { activity = new Activity(DiagnosticsHandlerLoggingStrings.ActivityName); } } return(activity); }
private Activity?StartActivity(HttpContext httpContext, bool loggingEnabled, bool diagnosticListenerActivityCreationEnabled, out bool hasDiagnosticListener) { var activity = _activitySource.CreateActivity(ActivityName, ActivityKind.Server); if (activity is null && (loggingEnabled || diagnosticListenerActivityCreationEnabled)) { activity = new Activity(ActivityName); } hasDiagnosticListener = false; if (activity is null) { return(null); } var headers = httpContext.Request.Headers; var requestId = headers.TraceParent; if (requestId.Count == 0) { requestId = headers.RequestId; } if (!StringValues.IsNullOrEmpty(requestId)) { activity.SetParentId(requestId); var traceState = headers.TraceState; if (traceState.Count > 0) { activity.TraceStateString = traceState; } // We expect baggage to be empty by default // Only very advanced users will be using it in near future, we encourage them to keep baggage small (few items) var baggage = headers.GetCommaSeparatedValues(HeaderNames.Baggage); if (baggage.Length == 0) { baggage = headers.GetCommaSeparatedValues(HeaderNames.CorrelationContext); } // AddBaggage adds items at the beginning of the list, so we need to add them in reverse to keep the same order as the client // An order could be important if baggage has two items with the same key (that is allowed by the contract) for (var i = baggage.Length - 1; i >= 0; i--) { if (NameValueHeaderValue.TryParse(baggage[i], out var baggageItem)) { activity.AddBaggage(baggageItem.Name.ToString(), HttpUtility.UrlDecode(baggageItem.Value.ToString())); } } } _diagnosticListener.OnActivityImport(activity, httpContext); if (_diagnosticListener.IsEnabled(ActivityStartKey)) { hasDiagnosticListener = true; StartActivity(activity, httpContext); } else { activity.Start(); } return(activity); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { this.logger.LogInformation("Starting ExecuteAsync for {TypeName}", this.GetType().Name); var poisonQueueName = $"{this.queueName}-poison"; var queueClient = this.queueServiceClient.GetQueueClient(this.queueName); var poisonQueueClient = this.queueServiceClient.GetQueueClient(poisonQueueName); await queueClient.CreateIfNotExistsAsync(); await poisonQueueClient.CreateIfNotExistsAsync(); while (true) { using var loopActivity = activitySource.CreateActivity("MessageLoopIteration", ActivityKind.Internal) ?? new Activity("MessageLoopIteration"); loopActivity?.AddBaggage("QueueName", queueClient.Name); using var loopOperation = this.telemetryClient.StartOperation <RequestTelemetry>(loopActivity); var options = this.options.CurrentValue; this.logger.LogDebug("Getting next message from queue {QueueName}", queueClient.Name); try { // We consider a message leased when it's made invisible in the queue and the current process has a // valid PopReceipt for the message. The PopReceipt is used to perform subsequent operations on the // "leased" message. QueueMessage message = await queueClient.ReceiveMessageAsync(options.MessageLeasePeriod); if (message == null) { this.logger.LogDebug("The queue returned no message. Waiting {Delay}.", options.EmptyQueuePollDelay); await Task.Delay(options.EmptyQueuePollDelay, stoppingToken); continue; } if (message.InsertedOn.HasValue) { this.telemetryClient.TrackMetric(new MetricTelemetry { Name = $"{this.queueName} MessageLatencyMs", Sum = DateTimeOffset.Now.Subtract(message.InsertedOn.Value).TotalMilliseconds }); } using (var activity = activitySource.CreateActivity("ProcessMessage", ActivityKind.Internal) ?? new Activity("ProcessMessage")) { activity?.AddBaggage("MessageId", message.MessageId); using var operation = this.telemetryClient.StartOperation <RequestTelemetry>(activity); try { this.logger.LogDebug("The queue returned a message.\n Queue: {Queue}\n Message: {MessageId}\n Dequeue Count: {DequeueCount}\n Pop Receipt: {PopReceipt}", queueClient.Name, message.MessageId, message.DequeueCount, message.PopReceipt); using var cts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken); // Because processing a message may take longer than our initial lease period, we want to continually // renew our lease until processing completes. var renewTask = RenewMessageLeaseAsync(queueClient, message, cts.Token); var processTask = SafelyProcessMessageAsync(message, cts.Token); var tasks = new Task[] { renewTask, processTask }; Task.WaitAny(tasks, CancellationToken.None); cts.Cancel(); Task.WaitAll(tasks, CancellationToken.None); // if the renew task doesn't complete successfully, we can't trust the PopReceipt on the message and must abort. var latestPopReceipt = await renewTask; if (processTask.IsCompletedSuccessfully && processTask.Result == true) { this.logger.LogDebug("Message processed successfully. Removing message from queue.\n MessageId: {MessageId}\n Queue: {QueueName}\n PopReceipt: {PopReceipt}", message.MessageId, queueClient.Name, latestPopReceipt); await queueClient.DeleteMessageAsync(message.MessageId, latestPopReceipt, stoppingToken); activity?.SetStatus(ActivityStatusCode.Ok); operation.Telemetry.Success = true; } else { activity?.SetStatus(ActivityStatusCode.Error); operation.Telemetry.Success = false; if (message.DequeueCount > options.MaxDequeueCount) { this.logger.LogError("Message {MessageId} exceeded maximum dequeue count. Moving to poison queue {QueueName}", message.MessageId, poisonQueueClient.Name); await poisonQueueClient.SendMessageAsync(message.Body, cancellationToken : stoppingToken); this.logger.LogDebug("Removing message from queue.\n MessageId: {MessageId}\n Queue: {QueueName}\n PopReceipt: {PopReceipt}", message.MessageId, queueClient.Name, latestPopReceipt); await queueClient.DeleteMessageAsync(message.MessageId, latestPopReceipt, stoppingToken); } else { this.logger.LogError("Resetting message visibility timeout to {SleepPeriod}.\n MessageId: {MessageId}\n Queue: {QueueName}\n PopReceipt: {PopReceipt}", options.MessageErrorSleepPeriod, message.MessageId, queueClient.Name, latestPopReceipt); await queueClient.UpdateMessageAsync(message.MessageId, latestPopReceipt, message.Body, options.MessageErrorSleepPeriod, cancellationToken : stoppingToken); } } } catch (Exception ex) { this.logger.LogError(ex, "Exception thrown while procesing queue message."); activity?.SetStatus(ActivityStatusCode.Error); operation.Telemetry.Success = false; } } } catch (Exception ex) { this.logger.LogError(ex, "Exception thrown while procesing message loop."); await Task.Delay(options.MessageErrorSleepPeriod, stoppingToken); } } }