forked from open-telemetry/opentelemetry-dotnet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add OTLP/HTTP binary protobuf trace exporter for .NET open-telemetry#…
…2292 (open-telemetry#2292) - HttpClient based Implementation - unit tests for OtlpHttpTraceExporter - added console test example using OtlpHttpTraceExporter
- Loading branch information
Showing
11 changed files
with
622 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// <copyright file="TestOtlpExporter.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using OpenTelemetry; | ||
using OpenTelemetry.Resources; | ||
using OpenTelemetry.Trace; | ||
|
||
namespace Examples.Console | ||
{ | ||
internal static class TestOtlpHttpExporter | ||
{ | ||
internal static object Run(string endpoint) | ||
{ | ||
// Adding the OtlpExporter creates a GrpcChannel. | ||
// This switch must be set before creating a GrpcChannel/HttpClient when calling an insecure gRPC service. | ||
// See: https://docs.microsoft.com/aspnet/core/grpc/troubleshoot#call-insecure-grpc-services-with-net-core-client | ||
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); | ||
|
||
// Enable OpenTelemetry for the sources "Samples.SampleServer" and "Samples.SampleClient" | ||
// and use OTLP over HTTP exporter. | ||
using var openTelemetry = Sdk.CreateTracerProviderBuilder() | ||
.AddSource("Samples.SampleClient", "Samples.SampleServer") | ||
.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("otlphttp-test")) | ||
.AddOtlpHttpExporter(opt => opt.Endpoint = new Uri(endpoint)) | ||
.Build(); | ||
|
||
// The above line is required only in Applications | ||
// which decide to use OpenTelemetry. | ||
using (var sample = new InstrumentationWithActivitySource()) | ||
{ | ||
sample.Start(); | ||
|
||
System.Console.WriteLine("Traces are being created and exported" + | ||
"to the OpenTelemetry Collector in the background. " + | ||
"Press ENTER to stop."); | ||
System.Console.ReadLine(); | ||
} | ||
|
||
return null; | ||
} | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
src/OpenTelemetry.Exporter.OpenTelemetryProtocol/BaseOtlpHttpExporter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// <copyright file="BaseOtlpHttpExporter.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation; | ||
using OtlpResource = Opentelemetry.Proto.Resource.V1; | ||
|
||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol | ||
{ | ||
/// <summary> | ||
/// Implements exporter that exports telemetry objects over OTLP/HTTP. | ||
/// </summary> | ||
/// <typeparam name="T">The type of telemetry object to be exported.</typeparam> | ||
public abstract class BaseOtlpHttpExporter<T> : BaseExporter<T> | ||
where T : class | ||
{ | ||
private OtlpResource.Resource processResource; | ||
private bool disposedValue; // To avoid duplicate dispose calls | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="BaseOtlpHttpExporter{T}"/> class. | ||
/// </summary> | ||
/// <param name="options">The <see cref="OtlpExporterOptions"/> for configuring the exporter.</param> | ||
/// <param name="httpHandler">The <see cref="IHttpHandler"/> used http requests.</param> | ||
protected BaseOtlpHttpExporter(OtlpExporterOptions options, IHttpHandler httpHandler = null) | ||
{ | ||
this.Options = options ?? throw new ArgumentNullException(nameof(options)); | ||
this.Headers = options.GetHeaders<Dictionary<string, string>>((d, k, v) => d.Add(k, v)); | ||
if (this.Options.TimeoutMilliseconds <= 0) | ||
{ | ||
throw new ArgumentException("Timeout value provided is not a positive number.", nameof(this.Options.TimeoutMilliseconds)); | ||
} | ||
|
||
this.HttpHandler = httpHandler ?? new HttpHandler(TimeSpan.FromMilliseconds(this.Options.TimeoutMilliseconds)); | ||
} | ||
|
||
internal OtlpResource.Resource ProcessResource => this.processResource ??= this.ParentProvider.GetResource().ToOtlpResource(); | ||
|
||
internal OtlpExporterOptions Options { get; } | ||
|
||
internal IReadOnlyDictionary<string, string> Headers { get; } | ||
|
||
internal IHttpHandler HttpHandler { get; } | ||
|
||
/// <inheritdoc/> | ||
protected override void Dispose(bool disposing) | ||
{ | ||
if (!this.disposedValue) | ||
{ | ||
if (disposing) | ||
{ | ||
this.HttpHandler?.Dispose(); | ||
} | ||
|
||
this.disposedValue = true; | ||
} | ||
|
||
base.Dispose(disposing); | ||
} | ||
|
||
/// <inheritdoc/> | ||
protected override bool OnShutdown(int timeoutMilliseconds) | ||
{ | ||
try | ||
{ | ||
this.HttpHandler.CancelPendingRequests(); | ||
return true; | ||
} | ||
catch (Exception ex) | ||
{ | ||
OpenTelemetryProtocolExporterEventSource.Log.ExportMethodException(ex); | ||
return false; | ||
} | ||
} | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/HttpHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// <copyright file="HttpHandler.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using System.Net.Http; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation | ||
{ | ||
/// <summary> | ||
/// Class decorating <see cref="System.Net.Http.HttpClient"/>. | ||
/// </summary> | ||
internal class HttpHandler : IHttpHandler | ||
{ | ||
internal readonly HttpClient HttpClient; | ||
|
||
public HttpHandler(TimeSpan timeout) | ||
{ | ||
this.HttpClient = new HttpClient | ||
{ | ||
Timeout = timeout, | ||
}; | ||
} | ||
|
||
public void CancelPendingRequests() | ||
{ | ||
this.HttpClient.CancelPendingRequests(); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
this.HttpClient.Dispose(); | ||
} | ||
|
||
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
return await this.HttpClient.SendAsync(request, cancellationToken); | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/IHttpHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// <copyright file="IHttpHandler.cs" company="OpenTelemetry Authors"> | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
// </copyright> | ||
|
||
using System; | ||
using System.Net.Http; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation | ||
{ | ||
/// <summary> | ||
/// Interface partialy exposing <see cref="HttpClient"/> methods. | ||
/// </summary> | ||
public interface IHttpHandler : IDisposable | ||
{ | ||
/// <summary> | ||
/// Cancel all pending requests on this instance. | ||
/// </summary> | ||
void CancelPendingRequests(); | ||
|
||
/// <summary> | ||
/// Send an HTTP request as an asynchronous operation. | ||
/// </summary> | ||
/// <param name="request">The HTTP request message to send.</param> | ||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param> | ||
/// <returns>Result of the export operation.</returns> | ||
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken = default); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpExporterOptionsCommonExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol | ||
{ | ||
internal static class OtlpExporterOptionsCommonExtensions | ||
{ | ||
internal static THeaders GetHeaders<THeaders>(this OtlpExporterOptions options, Action<THeaders, string, string> addHeader) | ||
where THeaders : new() | ||
{ | ||
var optionHeaders = options.Headers; | ||
var headers = new THeaders(); | ||
if (!string.IsNullOrEmpty(optionHeaders)) | ||
{ | ||
Array.ForEach( | ||
optionHeaders.Split(','), | ||
(pair) => | ||
{ | ||
// Specify the maximum number of substrings to return to 2 | ||
// This treats everything that follows the first `=` in the string as the value to be added for the metadata key | ||
var keyValueData = pair.Split(new char[] { '=' }, 2); | ||
if (keyValueData.Length != 2) | ||
{ | ||
throw new ArgumentException("Headers provided in an invalid format."); | ||
} | ||
|
||
var key = keyValueData[0].Trim(); | ||
var value = keyValueData[1].Trim(); | ||
addHeader(headers, key, value); | ||
}); | ||
} | ||
|
||
return headers; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.