Skip to content

Commit d4bea51

Browse files
authored
Fixes and refactoring for autoinstrumentation (#232)
Moves common code into `Elastic.OpenTelemetry.Core`. This project is not packaged, but the code is "compile included" into `Elastic.OpenTelemetry` and `Elastic.OpenTelemetry.AutoInstrumentation`. This allows `Elastic.OpenTelemetry.AutoInstrumentation` to contain the plugin and, with reduced dependencies, avoid any GAC issues. Also, refactors the `FileLogger` to remove the dependency on `System.Threading.Channels`, which presented issues when used for auto instrumentation.
1 parent ffd6291 commit d4bea51

File tree

64 files changed

+415
-342
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+415
-342
lines changed

Elastic.OpenTelemetry.sln

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
Microsoft Visual Studio Solution File, Format Version 12.00
32
# Visual Studio Version 17
43
VisualStudioVersion = 17.9.34321.82
@@ -62,6 +61,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApi", "test-applications
6261
EndProject
6362
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApiDotNet8", "test-applications\WebApiDotNet8\WebApiDotNet8\WebApiDotNet8.csproj", "{C8C543F8-5C7A-4748-A3E8-658D79E3FDC1}"
6463
EndProject
64+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.OpenTelemetry.Core", "src\Elastic.OpenTelemetry.Core\Elastic.OpenTelemetry.Core.csproj", "{C5E2CD91-3BD4-4CB8-9F82-52D600003537}"
65+
EndProject
6566
Global
6667
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6768
Debug|Any CPU = Debug|Any CPU
@@ -140,6 +141,10 @@ Global
140141
{C8C543F8-5C7A-4748-A3E8-658D79E3FDC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
141142
{C8C543F8-5C7A-4748-A3E8-658D79E3FDC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
142143
{C8C543F8-5C7A-4748-A3E8-658D79E3FDC1}.Release|Any CPU.Build.0 = Release|Any CPU
144+
{C5E2CD91-3BD4-4CB8-9F82-52D600003537}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
145+
{C5E2CD91-3BD4-4CB8-9F82-52D600003537}.Debug|Any CPU.Build.0 = Debug|Any CPU
146+
{C5E2CD91-3BD4-4CB8-9F82-52D600003537}.Release|Any CPU.ActiveCfg = Release|Any CPU
147+
{C5E2CD91-3BD4-4CB8-9F82-52D600003537}.Release|Any CPU.Build.0 = Release|Any CPU
143148
EndGlobalSection
144149
GlobalSection(SolutionProperties) = preSolution
145150
HideSolutionNode = FALSE
@@ -162,6 +167,7 @@ Global
162167
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {AAD39891-0B70-47FA-A212-43E1AAE5DF56}
163168
{2A1F61D6-EE54-4ECE-9814-A2BF34957415} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
164169
{C8C543F8-5C7A-4748-A3E8-658D79E3FDC1} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
170+
{C5E2CD91-3BD4-4CB8-9F82-52D600003537} = {E622CFF2-C6C4-40FB-BE42-7C4F2B38B75A}
165171
EndGlobalSection
166172
GlobalSection(ExtensibilityGlobals) = postSolution
167173
SolutionGuid = {573B2B5F-8CBB-4D52-A55A-4E65E282AAFB}

build/scripts/Packaging.fs

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ open Argu
1313
open BuildInformation
1414
open CommandLine
1515
open Octokit
16+
open Proc.Fs
1617

1718
///
1819
/// This module is hard to read, with so many file manipulations it's kinda hard to avoid.
@@ -49,26 +50,26 @@ let private distroAsset (asset: ReleaseAsset) = fileInfo distroFolder (asset.Nam
4950

5051
let pluginFiles tfm =
5152
["dll"; "pdb"; "xml"]
52-
|> List.map(fun e -> $"Elastic.OpenTelemetry.%s{e}")
53-
|> List.map(fun f -> Path.Combine(".artifacts", "bin", "Elastic.OpenTelemetry", $"release_%s{tfm}", "", f))
53+
|> List.map(fun e -> $"Elastic.OpenTelemetry.AutoInstrumentation.%s{e}")
54+
|> List.map(fun f -> Path.Combine(".artifacts", "bin", "Elastic.OpenTelemetry.AutoInstrumentation", $"release_%s{tfm}", "", f))
5455
|> List.map(fun f -> FileInfo(f))
55-
5656

5757
/// downloads the artifacts if they don't already exist locally
5858
let downloadArtifacts (_:ParseResults<Build>) =
59-
let client = GitHubClient(ProductHeaderValue("Elastic.OpenTelemetry"))
60-
let token = Environment.GetEnvironmentVariable("GITHUB_TOKEN")
59+
let client = GitHubClient(ProductHeaderValue "Elastic.OpenTelemetry")
60+
let token = Environment.GetEnvironmentVariable "GITHUB_TOKEN"
6161
if not(String.IsNullOrWhiteSpace(token)) then
6262
printfn "using GITHUB_TOKEN";
6363
let tokenAuth = Credentials(token);
6464
client.Credentials <- tokenAuth
6565

6666
let assets =
6767
async {
68-
let! release = client.Repository.Release.Get("open-telemetry", "opentelemetry-dotnet-instrumentation", $"v{otelAutoVersion.AsString}") |> Async.AwaitTask;
69-
Console.WriteLine($"Release %s{release.Name} has %i{release.Assets.Count} assets");
68+
let! release = client.Repository.Release.Get("open-telemetry",
69+
"opentelemetry-dotnet-instrumentation", $"v{otelAutoVersion.AsString}") |> Async.AwaitTask;
70+
Console.WriteLine $"Release %s{release.Name} has %i{release.Assets.Count} assets";
7071
return release.Assets
71-
|> Seq.map (fun asset -> (asset, downloadAsset asset))
72+
|> Seq.map (fun asset -> asset, downloadAsset asset)
7273
|> Seq.toList
7374
} |> Async.RunSynchronously
7475

@@ -78,9 +79,9 @@ let downloadArtifacts (_:ParseResults<Build>) =
7879
|> Seq.filter (fun (_, f) -> not f.Exists)
7980
|> Seq.iter (fun (asset, f) ->
8081
async {
81-
Console.WriteLine($"Retrieving {asset.Name}");
82-
let! fileData = httpClient.GetByteArrayAsync(asset.BrowserDownloadUrl) |> Async.AwaitTask
83-
Console.WriteLine($"Saving %i{fileData.Length} bytes to {f.FullName}")
82+
Console.WriteLine $"Retrieving {asset.Name}";
83+
let! fileData = httpClient.GetByteArrayAsync asset.BrowserDownloadUrl |> Async.AwaitTask
84+
Console.WriteLine $"Saving %i{fileData.Length} bytes to {f.FullName}"
8485
File.WriteAllBytes(f.FullName, fileData)
8586
f.Refresh()
8687
} |> Async.RunSynchronously
@@ -94,7 +95,7 @@ let injectPluginFiles (asset: ReleaseAsset) (stagedZip: FileInfo) tfm target =
9495
printfn $"Staging zip: %s{stagedZip.Name}, Adding: %s{f.Name} (%s{tfm}) to %s{target}"
9596
zipArchive.CreateEntryFromFile(f.FullName, Path.Combine(target, f.Name)) |> ignore
9697
)
97-
98+
9899
let injectPluginScripts (stagedZip: FileInfo) (otelScript: FileInfo) (script: FileInfo) =
99100
use zipArchive = ZipFile.Open(stagedZip.FullName, ZipArchiveMode.Update)
100101

@@ -106,7 +107,7 @@ let injectPluginScripts (stagedZip: FileInfo) (otelScript: FileInfo) (script: Fi
106107
entry.Delete()
107108

108109
zipArchive.CreateEntryFromFile(script.FullName, script.Name) |> ignore
109-
110+
110111
let stageInstrumentationScript (stagedZips:List<ReleaseAsset * FileInfo>) =
111112
let openTelemetryVersion = downloadFileInfo "opentelemetry-instrument.sh"
112113
let stageVersion = downloadFileInfo "_instrument.sh"
@@ -117,7 +118,7 @@ let stageInstrumentationScript (stagedZips:List<ReleaseAsset * FileInfo>) =
117118
let instrumentShZip =
118119
stagedZips
119120
|> List.map(fun (_, p) -> p)
120-
|> List.find (fun p -> not <| p.Name.EndsWith("-windows.zip"))
121+
|> List.find (fun p -> not <| p.Name.EndsWith "-windows.zip")
121122
use zipArchive = ZipFile.Open(instrumentShZip.FullName, ZipArchiveMode.Read)
122123
let shArchive = zipArchive.Entries |> Seq.find(fun e -> e.Name = "instrument.sh")
123124
shArchive.ExtractToFile openTelemetryVersion.FullName
@@ -142,12 +143,14 @@ let stageInstallationBashScript () =
142143

143144
let elasticInstall = distroFile installScript
144145
File.WriteAllText(elasticInstall.FullName, contents)
145-
let permissions =
146-
UnixFileMode.UserRead ||| UnixFileMode.UserWrite ||| UnixFileMode.UserExecute
147-
||| UnixFileMode.GroupRead ||| UnixFileMode.GroupWrite ||| UnixFileMode.GroupExecute
148-
||| UnixFileMode.OtherRead ||| UnixFileMode.OtherWrite ||| UnixFileMode.OtherExecute
149-
File.SetUnixFileMode(elasticInstall.FullName, permissions);
150-
146+
147+
if not (OperatingSystem.IsWindows()) then
148+
let permissions =
149+
UnixFileMode.UserRead ||| UnixFileMode.UserWrite ||| UnixFileMode.UserExecute
150+
||| UnixFileMode.GroupRead ||| UnixFileMode.GroupWrite ||| UnixFileMode.GroupExecute
151+
||| UnixFileMode.OtherRead ||| UnixFileMode.OtherWrite ||| UnixFileMode.OtherExecute
152+
File.SetUnixFileMode(elasticInstall.FullName, permissions);
153+
151154
let stageInstallationPsScript () =
152155
let installScript = downloadFileInfo "OpenTelemetry.DotNet.Auto.psm1"
153156
let staged = installScript.CopyTo ((stageFile installScript).FullName, true)
@@ -163,35 +166,34 @@ let stageInstallationPsScript () =
163166
[
164167
envMarker
165168
"#Elastic Distribution"
166-
"\"OTEL_DOTNET_AUTO_PLUGINS\" = \"Elastic.OpenTelemetry.AutoInstrumentationPlugin, Elastic.OpenTelemetry\""
169+
"\"OTEL_DOTNET_AUTO_PLUGINS\" = \"Elastic.OpenTelemetry.AutoInstrumentationPlugin, Elastic.OpenTelemetry.AutoInstrumentation\""
167170
]
168171
|> String.concat "\r\n "
169172
)
170173
.Replace("v" + Software.OpenTelemetryAutoInstrumentationVersion.AsString, Software.Version.NormalizeToShorter())
171174
let elasticInstall = distroFile installScript
172175
//ensure we write our new module name
173176
File.WriteAllText(elasticInstall.FullName.Replace("elastic.DotNet.Auto", "Elastic.OpenTelemetry.DotNet"), contents);
174-
175-
177+
176178
/// moves artifacts from open-distribution to elastic-distribution and renames them to `staged-dotnet-instrumentation*`.
177179
/// staged meaning we haven't injected our opentelemetry dll into the zip yet,
178180
let stageArtifacts (assets:List<ReleaseAsset * FileInfo>) =
179181
let stagedZips =
180182
assets
181-
|> List.filter(fun (a, _) -> a.Name.EndsWith(".zip"))
182-
|> List.filter(fun (a, _) -> not <| a.Name.EndsWith("nuget-packages.zip"))
183+
|> List.filter(fun (a, _) -> a.Name.EndsWith ".zip")
184+
|> List.filter(fun (a, _) -> not <| a.Name.EndsWith "nuget-packages.zip")
183185
|> List.map(fun (z, f) ->
184186
let stage = stageAsset z
185187
z, f.CopyTo(stage.FullName, true)
186188
)
187189

188-
let (otelScript, wrapperScript) = stageInstrumentationScript stagedZips
190+
let otelScript, wrapperScript = stageInstrumentationScript stagedZips
189191
printfn $"Staged (%s{wrapperScript.Name}) calling into (%s{otelScript.Name} for repackaging)"
190192

191193
stagedZips |> List.iter (fun (asset, path) ->
192194

193195
injectPluginFiles asset path "netstandard2.1" "net"
194-
if asset.Name.EndsWith("-windows.zip") then
196+
if asset.Name.EndsWith "-windows.zip" then
195197
injectPluginFiles asset path "net462" "netfx"
196198

197199
injectPluginScripts path otelScript wrapperScript
@@ -203,20 +205,16 @@ let stageArtifacts (assets:List<ReleaseAsset * FileInfo>) =
203205
printfn $"Moved staging to: %s{distro.FullName}"
204206
)
205207
stagedZips
206-
207-
208-
208+
209209
let redistribute (arguments:ParseResults<Build>) =
210+
exec { run "dotnet" "build" "src/Elastic.OpenTelemetry.AutoInstrumentation/Elastic.OpenTelemetry.AutoInstrumentation.csproj" "-f" "netstandard2.1" "-c" "release" }
211+
exec { run "dotnet" "build" "src/Elastic.OpenTelemetry.AutoInstrumentation/Elastic.OpenTelemetry.AutoInstrumentation.csproj" "-f" "net462" "-c" "release" }
210212
let assets = downloadArtifacts arguments
211213
printfn ""
212214
assets |> List.iter (fun (asset, path) ->
213215
printfn "Asset: %s" asset.Name
214216
)
215-
216217
stageInstallationBashScript()
217218
stageInstallationPsScript()
218219
let staged = stageArtifacts assets
219220
ignore()
220-
221-
222-

build/scripts/Targets.fs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,13 +130,12 @@ let private generateApiChanges _ =
130130
nugetPackages
131131
|> Seq.iter(fun p ->
132132
let outputFile = Path.Combine(output, $"breaking-changes-%s{p}.md")
133-
let tfm = "net8.0"
133+
let tfm = "net8.0" // We use net8.0 as AutoInstrumentation doesn't have a net9.0 target
134134
let args =
135135
[
136136
"assembly-differ"
137137
$"previous-nuget|%s{p}|%s{currentVersion}|%s{tfm}";
138-
//$"directory|.artifacts/bin/%s{p}/release/%s{tfm}";
139-
$"directory|.artifacts/bin/%s{p}/release_net9.0";
138+
$"directory|.artifacts/bin/%s{p}/release_%s{tfm}";
140139
"-a"; "true"; "--target"; p; "-f"; "github-comment"; "--output"; outputFile
141140
]
142141
exec { run "dotnet" args }
@@ -177,7 +176,7 @@ let Setup (parsed:ParseResults<Build>) =
177176
| Unit_Test -> Build.Cmd [] [Build] <| runTests Unit
178177
| Test -> Build.Cmd [] [Build] test
179178

180-
| Redistribute -> Build.Cmd [Compile;] [] Packaging.redistribute
179+
| Redistribute -> Build.Cmd [] [] Packaging.redistribute
181180

182181
| Release ->
183182
Build.Cmd

examples/Example.AutoInstrumentation/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ COPY --from=build_distro /work/.artifacts/bin/Elastic.OpenTelemetry/release_nets
5454
ENV CORECLR_ENABLE_PROFILING="1"
5555
ENV CORECLR_PROFILER="{918728DD-259F-4A6A-AC2B-B85E1B658318}"
5656
ENV CORECLR_PROFILER_PATH="/app/otel/linux-${TARGETARCH}/OpenTelemetry.AutoInstrumentation.Native.so"
57-
ENV OTEL_DOTNET_AUTO_PLUGINS="Elastic.OpenTelemetry.AutoInstrumentationPlugin, Elastic.OpenTelemetry, Version=1.0.0.0, Culture=neutral, PublicKeyToken=069ca2728db333c1"
57+
ENV OTEL_DOTNET_AUTO_PLUGINS="Elastic.OpenTelemetry.AutoInstrumentationPlugin, Elastic.OpenTelemetry.AutoInstrumentation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=069ca2728db333c1"
5858

5959
ENV OTEL_TRACES_EXPORTER=none
6060
ENV OTEL_METRICS_EXPORTER=none

examples/ServiceDefaults/ServiceDefaults.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="9.1.0" />
1414
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="9.0.0" />
15-
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.1" />
16-
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.1" />
15+
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.2" />
16+
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.2" />
1717
<PackageReference Include="OpenTelemetry.Instrumentation.GrpcNetClient" Version="1.11.0-beta.1" />
1818
<PackageReference Include="OpenTelemetry.Instrumentation.Process" Version="1.11.0-beta.1" />
1919
</ItemGroup>

src/Elastic.OpenTelemetry/Core/AutoInstrumentationPlugin.cs renamed to src/Elastic.OpenTelemetry.AutoInstrumentation/AutoInstrumentationPlugin.cs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
using Elastic.OpenTelemetry.Configuration;
66
using Elastic.OpenTelemetry.Core;
7+
using Elastic.OpenTelemetry.Diagnostics;
8+
using Microsoft.Extensions.Logging;
79
using OpenTelemetry;
810
using OpenTelemetry.Logs;
911
using OpenTelemetry.Metrics;
@@ -28,14 +30,53 @@ public class AutoInstrumentationPlugin
2830
/// <summary>
2931
/// To configure tracing SDK before Auto Instrumentation configured SDK.
3032
/// </summary>
31-
public TracerProviderBuilder BeforeConfigureTracerProvider(TracerProviderBuilder builder) =>
32-
builder.UseAutoInstrumentationElasticDefaults(_components);
33+
public TracerProviderBuilder BeforeConfigureTracerProvider(TracerProviderBuilder builder)
34+
{
35+
var logger = _components.Logger;
36+
37+
try
38+
{
39+
builder.ConfigureResource(r => r.WithElasticDefaults(_components, null));
40+
41+
CoreTracerProvderBuilderExtensions.AddActivitySourceWithLogging(builder, logger, "Elastic.Transport", "<n/a>");
42+
CoreTracerProvderBuilderExtensions.AddElasticProcessorsCore(builder, null, _components, null);
43+
44+
logger.LogConfiguredSignalProvider("Traces", nameof(TracerProviderBuilder), "<n/a>");
45+
46+
return builder;
47+
}
48+
catch (Exception ex)
49+
{
50+
logger.LogError(new EventId(520, "AutoInstrumentationTracerFailure"), ex,
51+
"Failed to register EDOT defaults for tracing auto-instrumentation to the TracerProviderBuilder.");
52+
}
53+
54+
return builder;
55+
}
3356

3457
/// <summary>
3558
/// To configure metrics SDK before Auto Instrumentation configured SDK.
3659
/// /// </summary>
37-
public MeterProviderBuilder BeforeConfigureMeterProvider(MeterProviderBuilder builder) =>
38-
builder.UseAutoInstrumentationElasticDefaults(_components);
60+
public MeterProviderBuilder BeforeConfigureMeterProvider(MeterProviderBuilder builder)
61+
{
62+
var logger = _components.Logger;
63+
64+
try
65+
{
66+
builder.ConfigureResource(r => r.WithElasticDefaults(_components, null));
67+
68+
logger.LogConfiguredSignalProvider(nameof(Signals.Metrics), nameof(MeterProviderBuilder), "<n/a>");
69+
70+
return builder;
71+
}
72+
catch (Exception ex)
73+
{
74+
logger.LogError(new EventId(521, "AutoInstrumentationTracerFailure"), ex,
75+
"Failed to register EDOT defaults for metrics auto-instrumentation to the MeterProviderBuilder.");
76+
}
77+
78+
return builder;
79+
}
3980

4081
/// <summary>
4182
/// To configure logs SDK (the method name is the same as for other logs options).

0 commit comments

Comments
 (0)