Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,4 @@ Copyright The OpenTelemetry Authors under Apache License Version 2.0
// .DependsOn(RunUnitTests)
// .DependsOn(RunIntegrationTests)
.DependsOn(this.PackAWSDistribution);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Microsoft.Extensions.Logging;
using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Logs;
using OpenTelemetry.Exporter;

namespace AWS.Distro.OpenTelemetry.Exporter.Xray.Udp;

Expand All @@ -16,40 +18,76 @@ public class OtlpExporterUtils
private static readonly ILogger Logger = Factory.CreateLogger<OtlpExporterUtils>();

private static readonly MethodInfo? WriteTraceDataMethod;
private static readonly MethodInfo? WriteLogsDataMethod;
private static readonly object? SdkLimitOptions;
private static readonly object? ExperimentalOptions;

static OtlpExporterUtils() {
Type? otlpSerializerType = Type.GetType("OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Serializer.ProtobufOtlpTraceSerializer, OpenTelemetry.Exporter.OpenTelemetryProtocol");
Type? otlpTraceSerializerType = Type.GetType("OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Serializer.ProtobufOtlpTraceSerializer, OpenTelemetry.Exporter.OpenTelemetryProtocol");
Type? otlpLogSerializerType = Type.GetType("OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.Serializer.ProtobufOtlpLogSerializer, OpenTelemetry.Exporter.OpenTelemetryProtocol");
Type? sdkLimitOptionsType = Type.GetType("OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.SdkLimitOptions, OpenTelemetry.Exporter.OpenTelemetryProtocol");
Type? experimentalOptionsType = Type.GetType("OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExperimentalOptions, OpenTelemetry.Exporter.OpenTelemetryProtocol");

if (sdkLimitOptionsType == null)
{
Logger.LogTrace("SdkLimitOptions Type was not found");
return;
}

if (otlpSerializerType == null)
if (experimentalOptionsType == null)
{
Logger.LogTrace("OtlpSerializer Type was not found");
Logger.LogTrace("ExperimentalOptions Type was not found");
return;
}

WriteTraceDataMethod = otlpSerializerType.GetMethod(
if (otlpTraceSerializerType == null)
{
Logger.LogTrace("OtlpTraceSerializer Type was not found");
return;
}

if (otlpLogSerializerType == null)
{
Logger.LogTrace("OtlpLogSerializer Type was not found");
return;
}

WriteTraceDataMethod = otlpTraceSerializerType.GetMethod(
"WriteTraceData",
BindingFlags.NonPublic | BindingFlags.Static,
null,
new[]
{
typeof(byte[]).MakeByRefType(), // ref byte[] buffer
typeof(int), // int writePosition
sdkLimitOptionsType, // SdkLimitOptions
sdkLimitOptionsType, // SdkLimitOptions
typeof(Resource), // Resource?
typeof(Batch<Activity>).MakeByRefType() // in Batch<Activity>
},
null)
?? throw new MissingMethodException("WriteTraceData not found"); // :contentReference[oaicite:1]{index=1}
?? throw new MissingMethodException("WriteTraceData not found");

// Get the WriteLogsData method from the ProtobufOtlpLogSerializer using reflection. "WriteLogsData" is based on the
// OpenTelemetry.Exporter.OpenTelemetryProtocol dependency found at
// https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpLogSerializer.cs
WriteLogsDataMethod = otlpLogSerializerType.GetMethod(
"WriteLogsData",
BindingFlags.NonPublic | BindingFlags.Static,
null,
new[]
{
typeof(byte[]).MakeByRefType(), // ref byte[] buffer
typeof(int), // int writePosition
sdkLimitOptionsType, // SdkLimitOptions
experimentalOptionsType, // ExperimentalOptions
typeof(Resource), // Resource?
typeof(Batch<LogRecord>).MakeByRefType() // in Batch<LogRecord>
},
null)
?? throw new MissingMethodException("WriteLogsData not found");

SdkLimitOptions = GetSdkLimitOptions();
ExperimentalOptions = GetExperimentalOptions();
}

// The WriteTraceData function builds writes data to the buffer byte[] object by calling private "WriteTraceData" function
Expand All @@ -71,7 +109,7 @@ public static int WriteTraceData(
// Pack arguments (ref/in remain by-ref in the args array)
object[] args = { buffer, writePosition, SdkLimitOptions, resource!, batch! };

// Invoke static method (null target) :contentReference[oaicite:2]{index=2}
// Invoke static method (null target)
var result = (int)WriteTraceDataMethod?.Invoke(obj: null, parameters: args)!;

// Unpack ref-buffer
Expand All @@ -80,8 +118,35 @@ public static int WriteTraceData(
return result;
}

// Uses reflection to the get the SdkLimitOptions required to invoke the ToOtlpSpan function used in the
// SerializeSpans function below. More information about SdkLimitOptions can be found in this link:
// The WriteLogsData function writes log data to the buffer byte[] object by calling private "WriteLogsData" function
// using reflection. "WriteLogsData" is based on the OpenTelemetry.Exporter.OpenTelemetryProtocol dependency found at
// https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/Serializer/ProtobufOtlpLogSerializer.cs
public static int WriteLogsData(
ref byte[] buffer,
int writePosition,
Resource? resource,
in Batch<LogRecord> batch)
{
if (SdkLimitOptions == null || ExperimentalOptions == null)
{
Logger.LogTrace("SdkLimitOptions or ExperimentalOptions Object was not found/created properly");
return -1;
}

// Pack arguments (ref/in remain by-ref in the args array)
object[] args = { buffer, writePosition, SdkLimitOptions, ExperimentalOptions, resource!, batch! };

// Invoke static method (null target)
var result = (int)WriteLogsDataMethod?.Invoke(obj: null, parameters: args)!;

// Unpack ref-buffer
buffer = (byte[])args[0];

return result;
}

// Uses reflection to get the SdkLimitOptions required to invoke the serialization functions.
// More information about SdkLimitOptions can be found in this link:
// https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/SdkLimitOptions.cs#L24
private static object? GetSdkLimitOptions()
{
Expand All @@ -97,4 +162,21 @@ public static int WriteTraceData(
object? sdkLimitOptionsInstance = Activator.CreateInstance(sdkLimitOptionsType);
return sdkLimitOptionsInstance;
}

// Uses reflection to get the ExperimentalOptions required for log serialization.
// More information about ExperimentalOptions can be found in the OpenTelemetry implementation:
// https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ExperimentalOptions.cs
private static object? GetExperimentalOptions()
{
Type? experimentalOptionsType = Type.GetType("OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExperimentalOptions, OpenTelemetry.Exporter.OpenTelemetryProtocol");
if (experimentalOptionsType == null)
{
Logger.LogTrace("ExperimentalOptions Type was not found");
return null;
}

// Create an instance of ExperimentalOptions using the default parameterless constructor
object? experimentalOptionsInstance = Activator.CreateInstance(experimentalOptionsType);
return experimentalOptionsInstance;
}
}
2 changes: 1 addition & 1 deletion sample-applications/integration-test-app/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ ENV OTEL_DOTNET_AUTO_PLUGINS="AWS.Distro.OpenTelemetry.AutoInstrumentation.Plugi
ENV OTEL_AWS_APPLICATION_SIGNALS_ENABLED="true"
ENV OTEL_TRACES_SAMPLER="always_on"
ENV OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
ENV OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT="http://otel:4318/v1/metrics"
ENV OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT="http://otel:4318/v1/metrics"
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ services:
ports:
- '8080:8080'
volumes:
- ~/.aws:/root/.aws:ro
- ~/.aws:/root/.aws:ro
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Net.Http;
using Amazon.S3;
using Microsoft.AspNetCore.Mvc;

namespace integration_test_app.Controllers;

[ApiController]
Expand Down Expand Up @@ -48,4 +48,4 @@ private string GetTraceId()
var random = traceId.Substring(8);
return "{" + "\"traceId\"" + ": " + "\"" + version + "-" + epoch + "-" + random + "\"" + "}";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
<AdditionalFiles Include="./stylecop.json" Link="stylecop.json" />
</ItemGroup>

</Project>
</Project>
Loading
Loading