Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ public class HomeController(IHttpClientFactory httpClientFactory) : Controller
public const string ActivitySourceName = "CustomActivitySource";
private static readonly ActivitySource ActivitySource = new(ActivitySourceName, "1.0.0");

private readonly IHttpClientFactory _httpClientFactory = httpClientFactory;

public async Task<IActionResult> Index()
{
using var client = httpClientFactory.CreateClient();
using var client = _httpClientFactory.CreateClient();

// ReSharper disable once ExplicitCallerInfoArgument
using var activity = ActivitySource.StartActivity("DoingStuff", ActivityKind.Internal);
Expand Down
11 changes: 5 additions & 6 deletions examples/Example.AspNetCore.Mvc/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
// Add services to the container.
builder.Services
.AddHttpClient()
.AddOpenTelemetry()
.ConfigureResource(r => r.AddService("MyNewService1"))
.WithElasticDefaults(builder.Configuration);
.AddElasticOpenTelemetry(builder.Configuration, logger)
.ConfigureResource(r => r.AddService("MyNewService1"));

builder.Services.AddOpenTelemetry()
.ConfigureResource(r => r.AddService("MyNewService2"))
.WithElasticDefaults(builder.Configuration);
//builder.Services.AddOpenTelemetry()
// .ConfigureResource(r => r.AddService("MyNewService2"))
// .WithElasticDefaults(builder.Configuration);

//OpenTelemetrySdk.Create(b => b.WithElasticDefaults(builder.Configuration));

Expand Down
5 changes: 2 additions & 3 deletions examples/ServiceDefaults/ServiceDefaults.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireSharedProject>true</IsAspireSharedProject>
Expand All @@ -16,7 +16,6 @@
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.9.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.GrpcNetClient" Version="1.11.0-beta.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.11.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.11.0-beta.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.11.0" />
</ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion src/Elastic.OpenTelemetry/Core/SignalBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public static bool ConfigureBuilder<T>(
// code in this particular case by shortcutting and returning early.
if (options is not null && components is not null)
{
ValidateGlobalCallCount(methodName, builderName, options, components, callCount);
configure(builder, components);
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions src/Elastic.OpenTelemetry/Diagnostics/LoggerMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ internal static partial class LoggerMessages
[LoggerMessage(EventId = 9, EventName = "AddedInstrumentation", Level = LogLevel.Information, Message = "Added {InstrumentationName} to {Provider}.")]
public static partial void LogAddedInstrumentation(this ILogger logger, string instrumentationName, string provider);

[LoggerMessage(EventId = 10, EventName = "HttpInstrumentationFound", Level = LogLevel.Information, Message = "The HTTP instrumentation library was located at '{AssemblyPath}'. " +
"Skipping adding native {InstrumentationType} instrumentation from the 'System.Net.Http' ActivitySource.")]
public static partial void LogHttpInstrumentationFound(this ILogger logger, string assemblyPath, string instrumentationType);

// We explictly reuse the same event ID and this is the same log message, but with different types for the structured data
[LoggerMessage(EventId = 9, Level = LogLevel.Debug, Message = "{ProcessorName} found `{AttributeName}` attribute with value '{AttributeValue}' on the span.")]
internal static partial void FoundTag(this ILogger logger, string processorName, string attributeName, string attributeValue);
Expand Down
8 changes: 4 additions & 4 deletions src/Elastic.OpenTelemetry/Elastic.OpenTelemetry.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
Expand All @@ -24,23 +24,23 @@
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.1" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.ElasticsearchClient" Version="1.0.0-beta.5" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.11.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.GrpcNetClient" Version="1.9.0-beta.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.EntityFrameworkCore" Version="1.0.0-beta.12" />
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="0.5.0-beta.6" />
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.9.0-beta.1" />
<PackageReference Include="OpenTelemetry.Resources.Host" Version="1.11.0-beta.1" />
<PackageReference Include="Polyfill" Version="7.16.1" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers; buildtransitive" />
<PackageReference Include="NetEscapades.EnumGenerators" Version="1.0.0-beta09" PrivateAssets="all" ExcludeAssets="runtime" />
<PackageReference Include="System.Text.Json" Version="9.0.1" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard2')) OR $(TargetFramework.StartsWith('net4'))">
<PackageReference Include="System.Threading.Channels" Version="9.0.1" />
<PackageReference Include="System.Threading.Channels" Version="9.0.2" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'net9.0'">
<PackageReference Include="System.Text.Json" Version="9.0.2" />
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.11.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.11.0" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,21 @@ private static InstrumentationAssemblyInfo[] GetReflectionInstrumentationAssembl
Filename = "OpenTelemetry.Instrumentation.AspNetCore.dll",
FullyQualifiedType = "OpenTelemetry.Metrics.AspNetCoreInstrumentationMeterProviderBuilderExtensions",
InstrumentationMethod = "AddAspNetCoreInstrumentation"
}
},
#if NET9_0_OR_GREATER
// On .NET 9, we add the `System.Net.Http` source for native instrumentation, rather than referencing
// the contrib instrumentation. However, if the consuming application has their own reference to
// `OpenTelemetry.Instrumentation.Http`, then we use that since it signals the consumer prefers the
// contrib instrumentation. Therefore, on .NET 9+ targets, we attempt to dynamically load the contrib
// instrumentation, when available.
new()
{
Name = "Http",
Filename = "OpenTelemetry.Instrumentation.Http.dll",
FullyQualifiedType = "OpenTelemetry.Metrics.HttpClientInstrumentationMeterProviderBuilderExtensions",
InstrumentationMethod = "AddHttpClientInstrumentation"
},
#endif
];

/// <summary>
Expand Down Expand Up @@ -156,8 +170,41 @@ static void ConfigureBuilder(MeterProviderBuilder builder, ElasticOpenTelemetryC
{
builder.ConfigureResource(r => r.AddElasticDistroAttributes());

AddWithLogging(builder, components.Logger, "HttpClient", b => b.AddHttpClientInstrumentation());
#if NET9_0_OR_GREATER
try
{
// This first check determines whether OpenTelemetry.Instrumentation.Http.dll is present, in which case,
// it will be registered on the builder via reflection. If it's not present, we can safely add the native
// source which is OTel compliant since .NET 9.
var assemblyLocation = Path.GetDirectoryName(typeof(ElasticOpenTelemetry).Assembly.Location);
if (assemblyLocation is not null)
{
var assemblyPath = Path.Combine(assemblyLocation, "OpenTelemetry.Instrumentation.Http.dll");

if (!File.Exists(assemblyPath))
{
AddWithLogging(builder, components.Logger, "Http (via native instrumentation)", b => b.AddMeter("System.Net.Http"));
}
else
{
components.Logger.LogHttpInstrumentationFound(assemblyPath, "metric");
}
}
}
catch (Exception ex)
{
components.Logger.LogError(ex, "An exception occurred while checking for the presence of `OpenTelemetry.Instrumentation.Http.dll`.");
}
#else
AddWithLogging(builder, components.Logger, "Http (via contrib instrumentation)", b => b.AddHttpClientInstrumentation());
#endif

AddWithLogging(builder, components.Logger, "Process", b => b.AddProcessInstrumentation());
#if NET9_0_OR_GREATER
AddWithLogging(builder, components.Logger, "Runtime", b => b.AddMeter("System.Runtime"));
#else
AddWithLogging(builder, components.Logger, "Runtime", b => b.AddRuntimeInstrumentation());
#endif

// TODO - Guard this behind runtime checks e.g. RuntimeFeature.IsDynamicCodeSupported to support AoT users.
// see https://github.com/elastic/elastic-otel-dotnet/issues/198
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,21 @@ private static InstrumentationAssemblyInfo[] GetReflectionInstrumentationAssembl
Filename = "OpenTelemetry.Instrumentation.AspNetCore.dll",
FullyQualifiedType = "OpenTelemetry.Trace.AspNetCoreInstrumentationTracerProviderBuilderExtensions",
InstrumentationMethod = "AddAspNetCoreInstrumentation"
}
},
#if NET9_0_OR_GREATER
// On .NET 9, we add the `System.Net.Http` source for native instrumentation, rather than referencing
// the contrib instrumentation. However, if the consuming application has their own reference to
// `OpenTelemetry.Instrumentation.Http`, then we use that since it signals the consumer prefers the
// contrib instrumentation. Therefore, on .NET 9+ targets, we attempt to dynamically load the contrib
// instrumentation, when available.
new()
{
Name = "Http",
Filename = "OpenTelemetry.Instrumentation.Http.dll",
FullyQualifiedType = "OpenTelemetry.Trace.HttpClientInstrumentationTracerProviderBuilderExtensions",
InstrumentationMethod = "AddHttpClientInstrumentation"
},
#endif
];

/// <summary>
Expand Down Expand Up @@ -147,7 +161,35 @@ static void ConfigureBuilder(TracerProviderBuilder builder, ElasticOpenTelemetry
{
builder.ConfigureResource(r => r.AddElasticDistroAttributes());

AddWithLogging(builder, components.Logger, "HttpClient", b => b.AddHttpClientInstrumentation());
#if NET9_0_OR_GREATER
try
{
// This first check determines whether OpenTelemetry.Instrumentation.Http.dll is present, in which case,
// it will be registered on the builder via reflection. If it's not present, we can safely add the native
// source which is OTel compliant since .NET 9.
var assemblyLocation = Path.GetDirectoryName(typeof(ElasticOpenTelemetry).Assembly.Location);
if (assemblyLocation is not null)
{
var assemblyPath = Path.Combine(assemblyLocation, "OpenTelemetry.Instrumentation.Http.dll");

if (!File.Exists(assemblyPath))
{
AddWithLogging(builder, components.Logger, "Http (via native instrumentation)", b => b.AddSource("System.Net.Http"));
}
else
{
components.Logger.LogHttpInstrumentationFound(assemblyPath, "trace");
}
}
}
catch (Exception ex)
{
components.Logger.LogError(ex, "An exception occurred while checking for the presence of `OpenTelemetry.Instrumentation.Http.dll`.");
}
#else
AddWithLogging(builder, components.Logger, "Http (via contrib instrumentation)", b => b.AddHttpClientInstrumentation());
#endif

AddWithLogging(builder, components.Logger, "GrpcClient", b => b.AddGrpcClientInstrumentation());
AddWithLogging(builder, components.Logger, "EntityFrameworkCore", b => b.AddEntityFrameworkCoreInstrumentation());
AddWithLogging(builder, components.Logger, "NEST", b => b.AddElasticsearchClientInstrumentation());
Expand Down Expand Up @@ -192,9 +234,9 @@ static void AddInstrumentationViaReflection(TracerProviderBuilder builder, ILogg
AddInstrumentationLibraryViaReflection(builder, logger, assemblyLocation, assembly);
}
}
catch
catch (Exception ex)
{
// TODO - Logging
logger.LogError(ex, "An exception occurred while adding instrumentation via reflection.");
}
}

Expand All @@ -207,7 +249,7 @@ static void AddInstrumentationLibraryViaReflection(
try
{
var assemblyPath = Path.Combine(assemblyLocation, info.Filename);
if (File.Exists(Path.Combine(assemblyLocation, info.Filename)))
if (File.Exists(assemblyPath))
{
logger.LogLocatedInstrumentationAssembly(info.Filename, assemblyLocation);

Expand Down
Loading