public LoggingStream(string requestId, ContentEventSourceWrapper eventSourceWrapper, int maxLoggedBytes, Stream originalStream, bool error, Encoding?textEncoding)
 {
     // Should only wrap non-seekable streams
     Debug.Assert(!originalStream.CanSeek);
     _requestId          = requestId;
     _eventSourceWrapper = eventSourceWrapper;
     _maxLoggedBytes     = maxLoggedBytes;
     _originalStream     = originalStream;
     _error        = error;
     _textEncoding = textEncoding;
 }
        private async ValueTask ProcessAsync(HttpPipelineMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            if (!s_eventSource.IsEnabled())
            {
                if (async)
                {
                    await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
                }
                else
                {
                    ProcessNext(message, pipeline);
                }
                return;
            }

            s_eventSource.Request(message.Request);

            Encoding?requestTextEncoding = null;

            if (message.Request.TryGetHeader(HttpHeader.Names.ContentType, out var contentType))
            {
                ContentTypeUtilities.TryGetTextEncoding(contentType, out requestTextEncoding);
            }

            var logWrapper = new ContentEventSourceWrapper(s_eventSource, _logContent, _maxLength, message.CancellationToken);

            await logWrapper.LogAsync(message.Request.ClientRequestId, message.Request.Content, requestTextEncoding, async).ConfigureAwait(false).EnsureCompleted(async);

            var before = Stopwatch.GetTimestamp();

            if (async)
            {
                await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
            }
            else
            {
                ProcessNext(message, pipeline);
            }

            var after = Stopwatch.GetTimestamp();

            bool isError = message.ResponseClassifier.IsErrorResponse(message);

            ContentTypeUtilities.TryGetTextEncoding(message.Response.Headers.ContentType, out Encoding? responseTextEncoding);

            bool wrapResponseContent = message.Response.ContentStream != null &&
                                       message.Response.ContentStream.CanSeek == false &&
                                       logWrapper.IsEnabled(isError);

            if (isError)
            {
                s_eventSource.ErrorResponse(message.Response);
            }
            else
            {
                s_eventSource.Response(message.Response);
            }

            if (wrapResponseContent)
            {
                message.Response.ContentStream = new LoggingStream(message.Response.ClientRequestId, logWrapper, _maxLength, message.Response.ContentStream !, isError, responseTextEncoding);
            }
            else
            {
                await logWrapper.LogAsync(message.Response.ClientRequestId, isError, message.Response.ContentStream, responseTextEncoding, async).ConfigureAwait(false).EnsureCompleted(async);
            }

            var elapsedMilliseconds = (after - before) * 1000 / Stopwatch.Frequency;

            if (elapsedMilliseconds > DelayWarningThreshold)
            {
                s_eventSource.ResponseDelay(message.Response, elapsedMilliseconds);
            }
        }
        private async ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory <HttpPipelinePolicy> pipeline, bool async)
        {
            Request request = message.Request;

            s_eventSource.Request(request.ClientRequestId, request.Method.ToString(), FormatUri(request.Uri), FormatHeaders(request.Headers), _assemblyName);

            Encoding?requestTextEncoding = null;

            if (request.TryGetHeader(HttpHeader.Names.ContentType, out var contentType))
            {
                ContentTypeUtilities.TryGetTextEncoding(contentType, out requestTextEncoding);
            }

            var logWrapper = new ContentEventSourceWrapper(s_eventSource, _logContent, _maxLength, message.CancellationToken);

            await logWrapper.LogAsync(request.ClientRequestId, request.Content, requestTextEncoding, async).ConfigureAwait(false).EnsureCompleted(async);

            var before = Stopwatch.GetTimestamp();

            try
            {
                if (async)
                {
                    await ProcessNextAsync(message, pipeline).ConfigureAwait(false);
                }
                else
                {
                    ProcessNext(message, pipeline);
                }
            }
            catch (Exception ex)
            {
                s_eventSource.ExceptionResponse(request.ClientRequestId, ex.ToString());
                throw;
            }

            var after = Stopwatch.GetTimestamp();

            bool isError = message.ResponseClassifier.IsErrorResponse(message);

            Response response = message.Response;

            ContentTypeUtilities.TryGetTextEncoding(response.Headers.ContentType, out Encoding? responseTextEncoding);

            bool wrapResponseContent = response.ContentStream != null &&
                                       response.ContentStream?.CanSeek == false &&
                                       logWrapper.IsEnabled(isError);

            double elapsed = (after - before) / (double)Stopwatch.Frequency;

            if (isError)
            {
                s_eventSource.ErrorResponse(response.ClientRequestId, response.Status, response.ReasonPhrase, FormatHeaders(response.Headers), elapsed);
            }
            else
            {
                s_eventSource.Response(response.ClientRequestId, response.Status, response.ReasonPhrase, FormatHeaders(response.Headers), elapsed);
            }

            if (wrapResponseContent)
            {
                response.ContentStream = new LoggingStream(response.ClientRequestId, logWrapper, _maxLength, response.ContentStream !, isError, responseTextEncoding);
            }
            else
            {
                await logWrapper.LogAsync(response.ClientRequestId, isError, response.ContentStream, responseTextEncoding, async).ConfigureAwait(false).EnsureCompleted(async);
            }

            if (elapsed > RequestTooLongTime)
            {
                s_eventSource.ResponseDelay(response.ClientRequestId, elapsed);
            }
        }