From 794b05f505cb654a62b3cda6196567eb3c659e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Kie=C5=82kowicz?= Date: Wed, 10 Apr 2024 06:27:48 +0200 Subject: [PATCH] Continuous Profiler - switch from obsolte HttpWebRequest to HttpClient (#446) It brings also support for CancellationToken --- .../ContinuousProfiler/OtlpHttpLogSender.cs | 68 +++++++++++-------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/src/Splunk.OpenTelemetry.AutoInstrumentation/ContinuousProfiler/OtlpHttpLogSender.cs b/src/Splunk.OpenTelemetry.AutoInstrumentation/ContinuousProfiler/OtlpHttpLogSender.cs index 90d61b14..6f19819c 100644 --- a/src/Splunk.OpenTelemetry.AutoInstrumentation/ContinuousProfiler/OtlpHttpLogSender.cs +++ b/src/Splunk.OpenTelemetry.AutoInstrumentation/ContinuousProfiler/OtlpHttpLogSender.cs @@ -16,6 +16,9 @@ #if NET6_0_OR_GREATER using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Runtime.CompilerServices; using OpenTelemetry; using Splunk.OpenTelemetry.AutoInstrumentation.Logging; using Splunk.OpenTelemetry.AutoInstrumentation.Proto.Logs.V1; @@ -30,6 +33,7 @@ internal class OtlpHttpLogSender private static readonly ILogger Logger = new Logger(); private readonly Uri _logsEndpointUrl; + private readonly HttpClient _httpClient = new(); public OtlpHttpLogSender(Uri logsEndpointUrl) { @@ -38,46 +42,56 @@ public OtlpHttpLogSender(Uri logsEndpointUrl) public void Send(LogsData logsData, CancellationToken cancellationToken) { - HttpWebRequest httpWebRequest; - - // Prevents the exporter's operations from being instrumented. - using var scope = SuppressInstrumentationScope.Begin(); try { - cancellationToken.ThrowIfCancellationRequested(); -#pragma warning disable SYSLIB0014 - // TODO muted SYSLIB0014 - httpWebRequest = WebRequest.CreateHttp(_logsEndpointUrl); -#pragma warning restore SYSLIB0014 - httpWebRequest.ContentType = "application/x-protobuf"; - httpWebRequest.Method = "POST"; - cancellationToken.ThrowIfCancellationRequested(); - using var stream = httpWebRequest.GetRequestStream(); - Vendors.ProtoBuf.Serializer.Serialize(stream, logsData); - cancellationToken.ThrowIfCancellationRequested(); + // Prevents the exporter's operations from being instrumented. + using var scope = SuppressInstrumentationScope.Begin(); - stream.Flush(); + using var request = new HttpRequestMessage(HttpMethod.Post, _logsEndpointUrl); + request.Content = new ExportLogsDataContent(logsData); + using var httpResponse = _httpClient.Send(request, cancellationToken); + httpResponse.EnsureSuccessStatusCode(); } catch (Exception ex) { - Logger.Error(ex, $"Exception preparing request to send thread samples to {_logsEndpointUrl}"); - return; + Logger.Error(ex, $"HTTP error sending thread samples to {_logsEndpointUrl}"); } + } - try + private sealed class ExportLogsDataContent : HttpContent + { + private static readonly MediaTypeHeaderValue ProtobufMediaTypeHeader = new("application/x-protobuf"); + + private readonly LogsData _logsData; + + public ExportLogsDataContent(LogsData logsData) { - using var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); + _logsData = logsData; + Headers.ContentType = ProtobufMediaTypeHeader; + } - if (httpWebResponse.StatusCode >= HttpStatusCode.OK && httpWebResponse.StatusCode < HttpStatusCode.MultipleChoices) - { - return; - } + protected override void SerializeToStream(Stream stream, TransportContext? context, CancellationToken cancellationToken) + { + SerializeToStreamInternal(stream); + } - Logger.Warning($"HTTP error sending thread samples to {_logsEndpointUrl}: {httpWebResponse.StatusCode}"); + protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) + { + SerializeToStreamInternal(stream); + return Task.CompletedTask; } - catch (Exception ex) + + protected override bool TryComputeLength(out long length) + { + // We can't know the length of the content being pushed to the output stream. + length = -1; + return false; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void SerializeToStreamInternal(Stream stream) { - Logger.Error(ex, $"Exception sending thread samples to {_logsEndpointUrl}"); + Vendors.ProtoBuf.Serializer.Serialize(stream, _logsData); } } }