Exemple #1
0
        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);
        }
Exemple #5
0
        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);
                }
            }
        }