diff --git a/sdk/core/Azure.Core/src/Diagnostics/AzureCoreEventSource.cs b/sdk/core/Azure.Core/src/Diagnostics/AzureCoreEventSource.cs index 436f148590cf..f3bcfda0fc00 100644 --- a/sdk/core/Azure.Core/src/Diagnostics/AzureCoreEventSource.cs +++ b/sdk/core/Azure.Core/src/Diagnostics/AzureCoreEventSource.cs @@ -12,24 +12,8 @@ namespace Azure.Core.Diagnostics [EventSource(Name = EventSourceName)] internal sealed class AzureCoreEventSource : AzureEventSource { - private const string EventSourceName = "Azure-Core"; + private const string EventSourceName = "Azure-Core-ext"; - private const int RequestEvent = 1; - private const int RequestContentEvent = 2; - private const int ResponseEvent = 5; - private const int ResponseContentEvent = 6; - private const int ResponseDelayEvent = 7; - private const int ErrorResponseEvent = 8; - private const int ErrorResponseContentEvent = 9; - private const int RequestRetryingEvent = 10; - private const int ResponseContentBlockEvent = 11; - private const int ErrorResponseContentBlockEvent = 12; - private const int ResponseContentTextEvent = 13; - private const int ErrorResponseContentTextEvent = 14; - private const int ResponseContentTextBlockEvent = 15; - private const int ErrorResponseContentTextBlockEvent = 16; - private const int RequestContentTextEvent = 17; - private const int ExceptionResponseEvent = 18; private const int BackgroundRefreshFailedEvent = 19; private const int RequestRedirectEvent = 20; private const int RequestRedirectBlockedEvent = 21; @@ -46,221 +30,6 @@ public void BackgroundRefreshFailed(string requestId, string exception) WriteEvent(BackgroundRefreshFailedEvent, requestId, exception); } - [NonEvent] - public void Request(Request request, string? assemblyName, HttpMessageSanitizer sanitizer) - { - if (IsEnabled(EventLevel.Informational, EventKeywords.None)) - { - Request(request.ClientRequestId, request.Method.ToString(), sanitizer.SanitizeUrl(request.Uri.ToString()), FormatHeaders(request.Headers, sanitizer), assemblyName); - } - } - - [Event(RequestEvent, Level = EventLevel.Informational, Message = "Request [{0}] {1} {2}\r\n{3}client assembly: {4}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with primitive types.")] - public void Request(string requestId, string method, string uri, string headers, string? clientAssembly) - { - WriteEvent(RequestEvent, requestId, method, uri, headers, clientAssembly); - } - - [NonEvent] - public void RequestContent(string requestId, byte[] content, Encoding? textEncoding) - { - if (IsEnabled(EventLevel.Verbose, EventKeywords.None)) - { - if (textEncoding is not null) - { - RequestContentText(requestId, textEncoding.GetString(content)); - } - else - { - RequestContent(requestId, content); - } - } - } - - [Event(RequestContentEvent, Level = EventLevel.Verbose, Message = "Request [{0}] content: {1}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with an array with primitive type elements.")] - public void RequestContent(string requestId, byte[] content) - { - WriteEvent(RequestContentEvent, requestId, content); - } - - [Event(RequestContentTextEvent, Level = EventLevel.Verbose, Message = "Request [{0}] content: {1}")] - public void RequestContentText(string requestId, string content) - { - WriteEvent(RequestContentTextEvent, requestId, content); - } - - [NonEvent] - public void Response(Response response, HttpMessageSanitizer sanitizer, double elapsed) - { - if (IsEnabled(EventLevel.Informational, EventKeywords.None)) - { - Response(response.ClientRequestId, response.Status, response.ReasonPhrase, FormatHeaders(response.Headers, sanitizer), elapsed); - } - } - - [Event(ResponseEvent, Level = EventLevel.Informational, Message = "Response [{0}] {1} {2} ({4:00.0}s)\r\n{3}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with primitive types.")] - public void Response(string requestId, int status, string reasonPhrase, string headers, double seconds) - { - WriteEvent(ResponseEvent, requestId, status, reasonPhrase, headers, seconds); - } - - [NonEvent] - public void ResponseContent(string requestId, byte[] content, Encoding? textEncoding) - { - if (IsEnabled(EventLevel.Verbose, EventKeywords.None)) - { - if (textEncoding is not null) - { - ResponseContentText(requestId, textEncoding.GetString(content)); - } - else - { - ResponseContent(requestId, content); - } - } - } - - [Event(ResponseContentEvent, Level = EventLevel.Verbose, Message = "Response [{0}] content: {1}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with an array with primitive type elements.")] - public void ResponseContent(string requestId, byte[] content) - { - WriteEvent(ResponseContentEvent, requestId, content); - } - - [Event(ResponseContentTextEvent, Level = EventLevel.Verbose, Message = "Response [{0}] content: {1}")] - public void ResponseContentText(string requestId, string content) - { - WriteEvent(ResponseContentTextEvent, requestId, content); - } - - [NonEvent] - public void ResponseContentBlock(string requestId, int blockNumber, byte[] content, Encoding? textEncoding) - { - if (IsEnabled(EventLevel.Verbose, EventKeywords.None)) - { - if (textEncoding is not null) - { - ResponseContentTextBlock(requestId, blockNumber, textEncoding.GetString(content)); - } - else - { - ResponseContentBlock(requestId, blockNumber, content); - } - } - } - - [Event(ResponseContentBlockEvent, Level = EventLevel.Verbose, Message = "Response [{0}] content block {1}: {2}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with an array with primitive type elements.")] - public void ResponseContentBlock(string requestId, int blockNumber, byte[] content) - { - WriteEvent(ResponseContentBlockEvent, requestId, blockNumber, content); - } - - [Event(ResponseContentTextBlockEvent, Level = EventLevel.Verbose, Message = "Response [{0}] content block {1}: {2}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with primitive types.")] - public void ResponseContentTextBlock(string requestId, int blockNumber, string content) - { - WriteEvent(ResponseContentTextBlockEvent, requestId, blockNumber, content); - } - - [NonEvent] - public void ErrorResponse(Response response, HttpMessageSanitizer sanitizer, double elapsed) - { - if (IsEnabled(EventLevel.Warning, EventKeywords.None)) - { - ErrorResponse(response.ClientRequestId, response.Status, response.ReasonPhrase, FormatHeaders(response.Headers, sanitizer), elapsed); - } - } - - [Event(ErrorResponseEvent, Level = EventLevel.Warning, Message = "Error response [{0}] {1} {2} ({4:00.0}s)\r\n{3}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with primitive types.")] - public void ErrorResponse(string requestId, int status, string reasonPhrase, string headers, double seconds) - { - WriteEvent(ErrorResponseEvent, requestId, status, reasonPhrase, headers, seconds); - } - - [NonEvent] - public void ErrorResponseContent(string requestId, byte[] content, Encoding? textEncoding) - { - if (IsEnabled(EventLevel.Informational, EventKeywords.None)) - { - if (textEncoding is not null) - { - ErrorResponseContentText(requestId, textEncoding.GetString(content)); - } - else - { - ErrorResponseContent(requestId, content); - } - } - } - - [Event(ErrorResponseContentEvent, Level = EventLevel.Informational, Message = "Error response [{0}] content: {1}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with an array with primitive type elements.")] - public void ErrorResponseContent(string requestId, byte[] content) - { - WriteEvent(ErrorResponseContentEvent, requestId, content); - } - - [Event(ErrorResponseContentTextEvent, Level = EventLevel.Informational, Message = "Error response [{0}] content: {1}")] - public void ErrorResponseContentText(string requestId, string content) - { - WriteEvent(ErrorResponseContentTextEvent, requestId, content); - } - - [NonEvent] - public void ErrorResponseContentBlock(string requestId, int blockNumber, byte[] content, Encoding? textEncoding) - { - if (IsEnabled(EventLevel.Informational, EventKeywords.None)) - { - if (textEncoding is not null) - { - ErrorResponseContentTextBlock(requestId, blockNumber, textEncoding.GetString(content)); - } - else - { - ErrorResponseContentBlock(requestId, blockNumber, content); - } - } - } - - [Event(ErrorResponseContentBlockEvent, Level = EventLevel.Informational, Message = "Error response [{0}] content block {1}: {2}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with an array with primitive type elements.")] - public void ErrorResponseContentBlock(string requestId, int blockNumber, byte[] content) - { - WriteEvent(ErrorResponseContentBlockEvent, requestId, blockNumber, content); - } - - [Event(ErrorResponseContentTextBlockEvent, Level = EventLevel.Informational, Message = "Error response [{0}] content block {1}: {2}")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with primitive types.")] - public void ErrorResponseContentTextBlock(string requestId, int blockNumber, string content) - { - WriteEvent(ErrorResponseContentTextBlockEvent, requestId, blockNumber, content); - } - - [Event(RequestRetryingEvent, Level = EventLevel.Informational, Message = "Request [{0}] attempt number {1} took {2:00.0}s")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with primitive types.")] - public void RequestRetrying(string requestId, int retryNumber, double seconds) - { - WriteEvent(RequestRetryingEvent, requestId, retryNumber, seconds); - } - - [Event(ResponseDelayEvent, Level = EventLevel.Warning, Message = "Response [{0}] took {1:00.0}s")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = "WriteEvent is used with primitive types.")] - public void ResponseDelay(string requestId, double seconds) - { - WriteEvent(ResponseDelayEvent, requestId, seconds); - } - - [Event(ExceptionResponseEvent, Level = EventLevel.Informational, Message = "Request [{0}] exception {1}")] - public void ExceptionResponse(string requestId, string exception) - { - WriteEvent(ExceptionResponseEvent, requestId, exception); - } - [NonEvent] public void RequestRedirect(Request request, Uri redirectUri, Response response) { diff --git a/sdk/core/Azure.Core/src/Pipeline/HttpPipelineBuilder.cs b/sdk/core/Azure.Core/src/Pipeline/HttpPipelineBuilder.cs index afba624f7d17..0c23d971342d 100644 --- a/sdk/core/Azure.Core/src/Pipeline/HttpPipelineBuilder.cs +++ b/sdk/core/Azure.Core/src/Pipeline/HttpPipelineBuilder.cs @@ -180,7 +180,7 @@ void AddNonNullPolicies(HttpPipelinePolicy[] policiesToAdd) { string assemblyName = buildOptions.ClientOptions.GetType().Assembly!.GetName().Name!; - policies.Add(new LoggingPolicy(diagnostics.IsLoggingContentEnabled, diagnostics.LoggedContentSizeLimit, sanitizer, assemblyName)); + policies.Add(new LoggingPolicy(diagnostics.IsLoggingContentEnabled, diagnostics.LoggedContentSizeLimit, diagnostics.LoggedHeaderNames.ToArray(), diagnostics.LoggedQueryParameters.ToArray(), assemblyName)); } policies.Add(new RequestActivityPolicy(isDistributedTracingEnabled, ClientDiagnostics.GetResourceProviderNamespace(buildOptions.ClientOptions.GetType().Assembly), sanitizer)); diff --git a/sdk/core/Azure.Core/src/Pipeline/Internal/LoggingPolicy.cs b/sdk/core/Azure.Core/src/Pipeline/Internal/LoggingPolicy.cs index 2c42e4fee132..98a5ce6df5b0 100644 --- a/sdk/core/Azure.Core/src/Pipeline/Internal/LoggingPolicy.cs +++ b/sdk/core/Azure.Core/src/Pipeline/Internal/LoggingPolicy.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.ClientModel.Primitives; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Tracing; @@ -15,401 +16,72 @@ namespace Azure.Core.Pipeline { internal class LoggingPolicy : HttpPipelinePolicy { - public LoggingPolicy(bool logContent, int maxLength, HttpMessageSanitizer sanitizer, string? assemblyName) - { - _sanitizer = sanitizer; - _logContent = logContent; - _maxLength = maxLength; - _assemblyName = assemblyName; - } - - private const double RequestTooLongTime = 3.0; // sec - - private static readonly AzureCoreEventSource s_eventSource = AzureCoreEventSource.Singleton; - - private readonly bool _logContent; - private readonly int _maxLength; - private readonly HttpMessageSanitizer _sanitizer; - private readonly string? _assemblyName; - - public override void Process(HttpMessage message, ReadOnlyMemory pipeline) - { - if (!s_eventSource.IsEnabled()) - { - ProcessNext(message, pipeline); - return; - } + private readonly LoggingPolicyAdapter _clientModelPolicy; - ProcessAsync(message, pipeline, false).EnsureCompleted(); - } - - public override ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory pipeline) + private static readonly string[] MainEventSourceTraits = { - if (!s_eventSource.IsEnabled()) - { - return ProcessNextAsync(message, pipeline); - } - - return ProcessAsync(message, pipeline, true); - } + AzureEventSourceListener.TraitName, + AzureEventSourceListener.TraitValue + }; - private async ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory pipeline, bool async) + public LoggingPolicy(bool logContent, int maxLength, string[] allowedHeaderNames, string[] allowedQueryParameters, string? assemblyName) { - Request request = message.Request; - - s_eventSource.Request(request, _assemblyName, _sanitizer); - - 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(); - - Response response = message.Response; - bool isError = response.IsError; - - ContentTypeUtilities.TryGetTextEncoding(response.Headers.ContentType, out Encoding? responseTextEncoding); - - bool wrapResponseContent = response.ContentStream != null && - message.BufferResponse == false && - logWrapper.IsEnabled(isError); - - double elapsed = (after - before) / (double)Stopwatch.Frequency; - - if (isError) + LoggingOptions loggingOptions = new() { - s_eventSource.ErrorResponse(response, _sanitizer, elapsed); - } - else - { - s_eventSource.Response(response, _sanitizer, elapsed); - } + LoggedContentSizeLimit = maxLength, + IsLoggingContentEnabled = logContent, + LoggedClientAssemblyName = assemblyName, + RequestIdHeaderName = "x-ms-client-request-id", + IsLoggingEnabled = true + }; - if (wrapResponseContent) + // Don't use the client model sanitization defaults because: + // 1. Azure.Core has its own defaults that are a superset and include Azure specific values + // 2. Avoid adding back a value that is a shared default between Azure.Core + // and System.ClientModel. ex: "ETag" is in both defaults, if an Azure library + // removes that, we don't want to add it back here through System.ClientModel defaults. + // 3. Also avoids duplicates. + loggingOptions.AllowedHeaderNames.Clear(); + loggingOptions.AllowedQueryParameters.Clear(); + foreach (var header in allowedHeaderNames) { - response.ContentStream = new LoggingStream(response.ClientRequestId, logWrapper, _maxLength, response.ContentStream!, isError, responseTextEncoding); + loggingOptions.AllowedHeaderNames.Add(header); } - else - { - await logWrapper.LogAsync(response.ClientRequestId, isError, response.ContentStream, responseTextEncoding, async).ConfigureAwait(false).EnsureCompleted(async); - } - - if (elapsed > RequestTooLongTime) + foreach (var query in allowedQueryParameters) { - s_eventSource.ResponseDelay(response.ClientRequestId, elapsed); + loggingOptions.AllowedQueryParameters.Add(query); } + _clientModelPolicy = new LoggingPolicyAdapter(this, loggingOptions); } - private class LoggingStream : ReadOnlyStream - { - private readonly string _requestId; - - private readonly ContentEventSourceWrapper _eventSourceWrapper; - - private int _maxLoggedBytes; - - private readonly Stream _originalStream; - - private readonly bool _error; - - private readonly Encoding? _textEncoding; - - private int _blockNumber; - - 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; - } - - public override long Seek(long offset, SeekOrigin origin) - { - return _originalStream.Seek(offset, origin); - } - - public override int Read(byte[] buffer, int offset, int count) - { - var result = _originalStream.Read(buffer, offset, count); - - var countToLog = result; - DecrementLength(ref countToLog); - LogBuffer(buffer, offset, countToLog); - - return result; - } - - private void LogBuffer(byte[] buffer, int offset, int count) - { - if (count == 0) - { - return; - } - - _eventSourceWrapper.Log(_requestId, _error, buffer, offset, count, _textEncoding, _blockNumber); - - _blockNumber++; - } - - public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { -#pragma warning disable CA1835 // ReadAsync(Memory<>) overload is not available in all targets - var result = await _originalStream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); -#pragma warning restore // ReadAsync(Memory<>) overload is not available in all targets - - var countToLog = result; - DecrementLength(ref countToLog); - LogBuffer(buffer, offset, countToLog); - - return result; - } + private static readonly AzureCoreEventSource s_eventSource = AzureCoreEventSource.Singleton; - public override bool CanRead => _originalStream.CanRead; - public override bool CanSeek => _originalStream.CanSeek; - public override long Length => _originalStream.Length; - public override long Position - { - get => _originalStream.Position; - set => _originalStream.Position = value; - } + public override void Process(HttpMessage message, ReadOnlyMemory pipeline) + => ProcessSyncOrAsync(message, pipeline, false).EnsureCompleted(); - public override void Close() - { - _originalStream.Close(); - } + public override async ValueTask ProcessAsync(HttpMessage message, ReadOnlyMemory pipeline) + => await ProcessSyncOrAsync(message, pipeline, true).ConfigureAwait(false); - protected override void Dispose(bool disposing) + private async ValueTask ProcessSyncOrAsync(HttpMessage message, ReadOnlyMemory pipeline, bool async) + { + HttpPipelineAdapter httpPipeline = new(pipeline); + if (async) { - base.Dispose(disposing); - - _originalStream.Dispose(); + await _clientModelPolicy.ProcessAsync(message, httpPipeline, -1).ConfigureAwait(false); } - - private void DecrementLength(ref int count) + else { - var left = Math.Min(count, _maxLoggedBytes); - count = left; - _maxLoggedBytes -= count; + _clientModelPolicy.Process(message, httpPipeline, -1); } } - private readonly struct ContentEventSourceWrapper + private sealed class LoggingPolicyAdapter : ClientLoggingPolicy { - private const int CopyBufferSize = 8 * 1024; - private readonly AzureCoreEventSource? _eventSource; - - private readonly int _maxLength; - - private readonly CancellationToken _cancellationToken; - - public ContentEventSourceWrapper(AzureCoreEventSource eventSource, bool logContent, int maxLength, CancellationToken cancellationToken) - { - _eventSource = logContent ? eventSource : null; - _maxLength = maxLength; - _cancellationToken = cancellationToken; - } - - public async ValueTask LogAsync(string requestId, bool isError, Stream? stream, Encoding? textEncoding, bool async) - { - EventType eventType = ResponseOrError(isError); - - if (stream == null || !IsEnabled(eventType)) - { - return; - } - - var bytes = await FormatAsync(stream, async).ConfigureAwait(false).EnsureCompleted(async); - Log(requestId, eventType, bytes, textEncoding); - } - - public async ValueTask LogAsync(string requestId, RequestContent? content, Encoding? textEncoding, bool async) - { - EventType eventType = EventType.Request; - - if (content == null || !IsEnabled(eventType)) - { - return; - } - - var bytes = await FormatAsync(content, async).ConfigureAwait(false).EnsureCompleted(async); - - Log(requestId, eventType, bytes, textEncoding); - } - - public void Log(string requestId, bool isError, byte[] buffer, int offset, int length, Encoding? textEncoding, int? block = null) - { - EventType eventType = ResponseOrError(isError); - - if (buffer == null || !IsEnabled(eventType)) - { - return; - } - - var logLength = Math.Min(length, _maxLength); - - byte[] bytes; - if (length == logLength && offset == 0) - { - bytes = buffer; - } - else - { - bytes = new byte[logLength]; - Array.Copy(buffer, offset, bytes, 0, logLength); - } - - Log(requestId, eventType, bytes, textEncoding, block); - } + private readonly LoggingPolicy _azureCorePolicy; - public bool IsEnabled(bool isError) + public LoggingPolicyAdapter(LoggingPolicy azureCorePolicy, LoggingOptions options) : base("Azure-Core", MainEventSourceTraits, options) { - return IsEnabled(ResponseOrError(isError)); - } - - private bool IsEnabled(EventType errorResponse) - { - return _eventSource != null && - (_eventSource.IsEnabled(EventLevel.Informational, EventKeywords.All) || - (errorResponse == EventType.ErrorResponse && _eventSource.IsEnabled(EventLevel.Warning, EventKeywords.All))); - } - - private async ValueTask FormatAsync(RequestContent requestContent, bool async) - { - using var memoryStream = new MaxLengthStream(_maxLength); - - if (async) - { - await requestContent.WriteToAsync(memoryStream, _cancellationToken).ConfigureAwait(false); - } - else - { - requestContent.WriteTo(memoryStream, _cancellationToken); - } - - return memoryStream.ToArray(); - } - - private async ValueTask FormatAsync(Stream content, bool async) - { - using var memoryStream = new MaxLengthStream(_maxLength); - - if (async) - { - await content.CopyToAsync(memoryStream, CopyBufferSize, _cancellationToken).ConfigureAwait(false); - } - else - { - content.CopyTo(memoryStream); - } - - content.Seek(0, SeekOrigin.Begin); - - return memoryStream.ToArray(); - } - - private void Log(string requestId, EventType eventType, byte[] bytes, Encoding? textEncoding, int? block = null) - { - // We checked IsEnabled before we got here - Debug.Assert(_eventSource != null); - AzureCoreEventSource azureCoreEventSource = _eventSource!; - - switch (eventType) - { - case EventType.Request: - azureCoreEventSource.RequestContent(requestId, bytes, textEncoding); - break; - - // Response - case EventType.Response when block != null: - azureCoreEventSource.ResponseContentBlock(requestId, block.Value, bytes, textEncoding); - break; - case EventType.Response: - azureCoreEventSource.ResponseContent(requestId, bytes, textEncoding); - break; - - // ResponseError - case EventType.ErrorResponse when block != null: - azureCoreEventSource.ErrorResponseContentBlock(requestId, block.Value, bytes, textEncoding); - break; - case EventType.ErrorResponse: - azureCoreEventSource.ErrorResponseContent(requestId, bytes, textEncoding); - break; - } - } - - private static EventType ResponseOrError(bool isError) - { - return isError ? EventType.ErrorResponse : EventType.Response; - } - - private enum EventType - { - Request, - Response, - ErrorResponse - } - - private class MaxLengthStream : MemoryStream - { - private int _bytesLeft; - - public MaxLengthStream(int maxLength) : base() - { - _bytesLeft = maxLength; - } - - public override void Write(byte[] buffer, int offset, int count) - { - DecrementLength(ref count); - if (count > 0) - { - base.Write(buffer, offset, count); - } - } - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - return count > 0 ? base.WriteAsync(buffer, offset, count, cancellationToken) : Task.CompletedTask; - } - - private void DecrementLength(ref int count) - { - var left = Math.Min(count, _bytesLeft); - count = left; - - _bytesLeft -= count; - } + _azureCorePolicy = azureCorePolicy; } } } diff --git a/sdk/core/Azure.Core/src/Pipeline/RedirectPolicy.cs b/sdk/core/Azure.Core/src/Pipeline/RedirectPolicy.cs index f62e324ac792..95d56cdf0aa2 100644 --- a/sdk/core/Azure.Core/src/Pipeline/RedirectPolicy.cs +++ b/sdk/core/Azure.Core/src/Pipeline/RedirectPolicy.cs @@ -22,7 +22,7 @@ public sealed class RedirectPolicy : HttpPipelinePolicy /// /// Creates a new instance of the class. /// - /// Determinds whether redirects will be handled by this policy. Rather than passing false, consider using the static instance instead which defaults to false. + /// Determines whether redirects will be handled by this policy. Rather than passing false, consider using the static instance instead which defaults to false. internal RedirectPolicy(bool allowAutoRedirect) { _allowAutoRedirects = allowAutoRedirect; diff --git a/sdk/core/Azure.Core/src/Pipeline/RetryPolicy.cs b/sdk/core/Azure.Core/src/Pipeline/RetryPolicy.cs index 53e98789b7a5..6dd3cf444b00 100644 --- a/sdk/core/Azure.Core/src/Pipeline/RetryPolicy.cs +++ b/sdk/core/Azure.Core/src/Pipeline/RetryPolicy.cs @@ -254,10 +254,6 @@ protected override void OnTryComplete(PipelineMessage message) return; } - // This logic can move into System.ClientModel's ClientRetryPolicy - // once we enable EventSource logging there. - AzureCoreEventSource.Singleton.RequestRetrying(httpMessage.Request.ClientRequestId, httpMessage.RetryNumber, elapsed); - // Reset stopwatch values message.SetProperty(typeof(BeforeTimestamp), null); message.SetProperty(typeof(ElapsedTime), null); diff --git a/sdk/core/System.ClientModel/src/Pipeline/ClientLoggingPolicy.cs b/sdk/core/System.ClientModel/src/Pipeline/ClientLoggingPolicy.cs index da98a8592045..d8270daf0add 100644 --- a/sdk/core/System.ClientModel/src/Pipeline/ClientLoggingPolicy.cs +++ b/sdk/core/System.ClientModel/src/Pipeline/ClientLoggingPolicy.cs @@ -12,6 +12,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Linq; namespace System.ClientModel.Primitives; @@ -46,7 +47,7 @@ protected ClientLoggingPolicy(string logName, string[]? logTraits = default, Log _assemblyName = loggingOptions.LoggedClientAssemblyName; _clientRequestIdHeaderName = loggingOptions.RequestIdHeaderName; _isLoggingEnabled = loggingOptions.IsLoggingEnabled; - _sanitizer = new PipelineMessageSanitizer(loggingOptions.AllowedQueryParameters, loggingOptions.AllowedHeaderNames); + _sanitizer = new PipelineMessageSanitizer(loggingOptions.AllowedQueryParameters.ToArray(), loggingOptions.AllowedHeaderNames.ToArray()); string logNameToUse = logName ?? DefaultEventSourceName; EventSourceSingleton = s_singletonEventSources.GetOrAdd(logNameToUse, _ => ClientModelEventSource.Create(logNameToUse, logTraits));