From dfffae63ceadf90bf920e190a399ff2eba5ac29f Mon Sep 17 00:00:00 2001 From: Jakub Majocha <1760221+majocha@users.noreply.github.com> Date: Mon, 13 Jan 2025 16:19:38 +0100 Subject: [PATCH] OpenTelemetry instrumentation for xUnit tests (#18230) * otel instrumentation for xunit test runs * wip * sort out deps version conflict * disable for desktop --- .../FSharpChecker/CommonWorkflows.fs | 11 ---------- .../FSharpChecker/TransparentCompiler.fs | 7 ------ .../FSharp.Test.Utilities.fsproj | 2 +- .../ProjectGeneration.fs | 11 ---------- tests/FSharp.Test.Utilities/XunitHelpers.fs | 22 +++++++++++++++++++ 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs index 4b0163a9f4b..d8bd1f6e262 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/CommonWorkflows.fs @@ -143,14 +143,6 @@ let ``Using getSource and notifications instead of filesystem`` () = [] let GetAllUsesOfAllSymbols() = - let traceProvider = - Sdk.CreateTracerProviderBuilder() - .AddSource("fsc") - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName="F#", serviceVersion = "1")) - .AddJaegerExporter() - .Build() - - use _ = Activity.start "GetAllUsesOfAllSymbols" [ ] let result = async { @@ -162,9 +154,6 @@ let GetAllUsesOfAllSymbols() = return checkProjectResults.GetAllUsesOfAllSymbols() } |> Async.RunSynchronously - traceProvider.ForceFlush() |> ignore - traceProvider.Dispose() - if result.Length <> 79 then failwith $"Expected 81 symbolUses, got {result.Length}:\n%A{result}" [] diff --git a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs index b523b814b72..33ac7992e14 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs +++ b/tests/FSharp.Compiler.ComponentTests/FSharpChecker/TransparentCompiler.fs @@ -556,13 +556,6 @@ let fuzzingTest seed (project: SyntheticProject) = task { do! Task.Delay (rng.Next maxCheckingDelayMs) } - use _tracerProvider = - Sdk.CreateTracerProviderBuilder() - .AddSource("fsc") - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName="F# Fuzzing", serviceVersion = "1")) - .AddJaegerExporter() - .Build() - use _ = Activity.start $"Fuzzing {project.Name}" [ Activity.Tags.project, project.Name; "seed", seed.ToString() ] do! task { diff --git a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj index 1e3fd1b84c9..5b8f66bac7d 100644 --- a/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj +++ b/tests/FSharp.Test.Utilities/FSharp.Test.Utilities.fsproj @@ -108,7 +108,7 @@ - + diff --git a/tests/FSharp.Test.Utilities/ProjectGeneration.fs b/tests/FSharp.Test.Utilities/ProjectGeneration.fs index 1734e3240a7..92256c2b09b 100644 --- a/tests/FSharp.Test.Utilities/ProjectGeneration.fs +++ b/tests/FSharp.Test.Utilities/ProjectGeneration.fs @@ -961,7 +961,6 @@ type ProjectWorkflowBuilder let mutable latestProject = initialProject let mutable activity = None - let mutable tracerProvider = None let getSource f = f |> getSourceText latestProject :> ISourceText |> Some |> async.Return @@ -1010,13 +1009,6 @@ type ProjectWorkflowBuilder member this.Yield _ = async { let! ctx = getInitialContext() - tracerProvider <- - Sdk.CreateTracerProviderBuilder() - .AddSource("fsc") - .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(serviceName="F#", serviceVersion = "1")) - .AddJaegerExporter() - .Build() - |> Some activity <- Activity.start ctx.Project.Name [ Activity.Tags.project, ctx.Project.Name; "UsingTransparentCompiler", useTransparentCompiler.ToString() ] |> Some return ctx } @@ -1032,9 +1024,6 @@ type ProjectWorkflowBuilder if initialContext.IsNone && not isExistingProject then this.DeleteProjectDir() activity |> Option.iter (fun x -> if not (isNull x) then x.Dispose()) - tracerProvider |> Option.iter (fun x -> - x.ForceFlush() |> ignore - x.Dispose()) member this.Run(workflow: Async) = if autoStart then diff --git a/tests/FSharp.Test.Utilities/XunitHelpers.fs b/tests/FSharp.Test.Utilities/XunitHelpers.fs index 7a41338200a..3a0049df5a8 100644 --- a/tests/FSharp.Test.Utilities/XunitHelpers.fs +++ b/tests/FSharp.Test.Utilities/XunitHelpers.fs @@ -10,6 +10,12 @@ open Xunit.Abstractions open TestFramework +open FSharp.Compiler.Diagnostics + +open OpenTelemetry +open OpenTelemetry.Resources +open OpenTelemetry.Trace + /// Disables custom internal parallelization added with XUNIT_EXTRAS. /// Execute test cases in a class or a module one by one instead of all at once. Allow other collections to run simultaneously. [] @@ -45,6 +51,7 @@ type ConsoleCapturingTestRunner(test, messageBus, testClass, constructorArgument override this.InvokeTestAsync (aggregator: ExceptionAggregator) = task { use capture = new TestConsole.ExecutionCapture() + use _ = Activity.start test.DisplayName [ ] let! executionTime = this.BaseInvokeTestMethodAsync aggregator let output = seq { @@ -139,9 +146,24 @@ type FSharpXunitFramework(sink: IMessageSink) = log "FSharpXunitFramework with XUNIT_EXTRAS installing TestConsole redirection" TestConsole.install() +// TODO: Currently does not work with Desktop .NET Framework. Upcoming OpenTelemetry 1.11.0 may change it. +#if NETCOREAPP + let traceProvider = + Sdk.CreateTracerProviderBuilder() + .AddSource(ActivityNames.FscSourceName) + .SetResourceBuilder( + ResourceBuilder.CreateDefault().AddService(serviceName="F#", serviceVersion = "1.0.0")) + .AddOtlpExporter() + .Build() +#endif + interface IDisposable with member _.Dispose() = cleanUpTemporaryDirectoryOfThisTestRun () +#if NETCOREAPP + traceProvider.ForceFlush() |> ignore + traceProvider.Dispose() +#endif base.Dispose() override this.CreateDiscoverer (assemblyInfo) =