-
-
Notifications
You must be signed in to change notification settings - Fork 237
Add OTEL tracing support for Wiremock + automatic OTEL for Aspire integration #1418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
d293b96
Update aspire to 13.1 (examples + code)
petrroll 40a4a7f
Add OTEL support
petrroll 665f407
Initial PR feedback
petrroll 9f425e3
PR feedback
petrroll 9a065d2
PR feedback
petrroll 648baea
PR feedback
petrroll 296d134
Cleanup.
petrroll 652b088
Cleanup
petrroll e21ce10
Fix
petrroll 1536588
Fix
petrroll ff4d7da
Rename stuff around to be more accurate
petrroll a03cf35
PR feedback
petrroll 95e76dd
Update WireMock.Net.OpenTelemetry.csproj
StefH 3915ae0
PR feedback parser
petrroll 5e772d1
PR feedback package versions
petrroll 9d52c2c
Status code feedback.
petrroll e890836
Update preprocessor directives to to Activity Tracing instead of Open…
petrroll ef520cf
Merge branch 'petrhouska/otel-support' of https://github.com/petrroll…
petrroll f830822
Add tests
petrroll 88588b8
Improve tests
petrroll File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,141 @@ | ||
| // Copyright © WireMock.Net | ||
| // OpenTelemetry Tracing Demo for WireMock.Net | ||
| // This demo uses the Console Exporter to visualize traces in the terminal. | ||
|
|
||
| using OpenTelemetry; | ||
| using OpenTelemetry.Trace; | ||
| using WireMock.Server; | ||
| using WireMock.Settings; | ||
| using WireMock.RequestBuilders; | ||
| using WireMock.ResponseBuilders; | ||
| using WireMock.OpenTelemetry; | ||
|
|
||
| Console.WriteLine("=== WireMock.Net OpenTelemetry Tracing Demo ===\n"); | ||
|
|
||
| // WireMock.Net creates Activity objects using System.Diagnostics.Activity (built into .NET). | ||
| // These activities are automatically created when ActivityTracingEnabled is set to true. | ||
| // | ||
| // To export these traces, you have two options: | ||
| // | ||
| // Option 1: Configure your own TracerProvider (shown below) | ||
| // - Full control over exporters (Console, OTLP, Jaeger, etc.) | ||
| // - Add additional instrumentation (HttpClient, database, etc.) | ||
| // - Recommended for most applications | ||
| // | ||
| // Option 2: Use WireMock.Net.OpenTelemetry package | ||
| // - Reference the WireMock.Net.OpenTelemetry NuGet package | ||
| // - Use services.AddWireMockOpenTelemetry(openTelemetryOptions) | ||
| // - Adds WireMock + ASP.NET Core instrumentation and OTLP exporter | ||
| // - Good for quick setup with all-in-one configuration | ||
|
|
||
| // Option 1: Custom TracerProvider with Console exporter for this demo | ||
| using var tracerProvider = Sdk.CreateTracerProviderBuilder() | ||
| .AddWireMockInstrumentation(new OpenTelemetryOptions() { ExcludeAdminRequests = true }) | ||
| .AddHttpClientInstrumentation() // HTTP client traces (for our test requests) | ||
| .AddConsoleExporter() // Export traces to console for demo purposes | ||
| .Build(); | ||
|
|
||
| Console.WriteLine("Console Exporter configured to visualize:"); | ||
| Console.WriteLine(" - WireMock.Net traces (wiremock.* tags)"); | ||
| Console.WriteLine(" - ASP.NET Core server traces"); | ||
| Console.WriteLine(" - HTTP client traces\n"); | ||
|
|
||
| // Start WireMock server with OpenTelemetry enabled (ActivityTracingOptions != null enables tracing) | ||
| var server = WireMockServer.Start(new WireMockServerSettings | ||
| { | ||
| StartAdminInterface = true, | ||
| ActivityTracingOptions = new ActivityTracingOptions | ||
| { | ||
| ExcludeAdminRequests = true | ||
| } | ||
| }); | ||
|
|
||
| Console.WriteLine($"WireMock server started at: {string.Join(", ", server.Urls)}\n"); | ||
|
|
||
| // Configure some mock mappings | ||
| server | ||
| .Given(Request.Create() | ||
| .WithPath("/api/hello") | ||
| .UsingGet()) | ||
| .RespondWith(Response.Create() | ||
| .WithStatusCode(200) | ||
| .WithBody("Hello from WireMock!")); | ||
|
|
||
| server | ||
| .Given(Request.Create() | ||
| .WithPath("/api/user/*") | ||
| .UsingGet()) | ||
| .RespondWith(Response.Create() | ||
| .WithStatusCode(200) | ||
| .WithHeader("Content-Type", "application/json") | ||
| .WithBody(@"{""name"": ""John Doe"", ""email"": ""john@example.com""}")); | ||
|
|
||
| server | ||
| .Given(Request.Create() | ||
| .WithPath("/api/error") | ||
| .UsingGet()) | ||
| .RespondWith(Response.Create() | ||
| .WithStatusCode(500) | ||
| .WithBody("Internal Server Error")); | ||
|
|
||
| Console.WriteLine("Mock mappings configured:"); | ||
| Console.WriteLine(" GET /api/hello -> 200 OK"); | ||
| Console.WriteLine(" GET /api/user/* -> 200 OK (JSON)"); | ||
| Console.WriteLine(" GET /api/error -> 500 Error"); | ||
| Console.WriteLine(); | ||
|
|
||
| // Make some test requests to generate traces | ||
| using var httpClient = server.CreateClient(); | ||
|
|
||
| Console.WriteLine("Making test requests to generate traces...\n"); | ||
| Console.WriteLine("─────────────────────────────────────────────────────────────────"); | ||
|
|
||
| // Request 1: Successful request | ||
| Console.WriteLine("\n>>> Request 1: GET /api/hello"); | ||
| var response1 = await httpClient.GetAsync("/api/hello"); | ||
| Console.WriteLine($"<<< Response: {(int)response1.StatusCode} {response1.StatusCode}"); | ||
| Console.WriteLine($" Body: {await response1.Content.ReadAsStringAsync()}"); | ||
|
|
||
| await Task.Delay(500); // Small delay to let trace export complete | ||
|
|
||
| // Request 2: Another successful request with path parameter | ||
| Console.WriteLine("\n>>> Request 2: GET /api/user/123"); | ||
| var response2 = await httpClient.GetAsync("/api/user/123"); | ||
| Console.WriteLine($"<<< Response: {(int)response2.StatusCode} {response2.StatusCode}"); | ||
| Console.WriteLine($" Body: {await response2.Content.ReadAsStringAsync()}"); | ||
|
|
||
| await Task.Delay(500); | ||
|
|
||
| // Request 3: Error response | ||
| Console.WriteLine("\n>>> Request 3: GET /api/error"); | ||
| var response3 = await httpClient.GetAsync("/api/error"); | ||
| Console.WriteLine($"<<< Response: {(int)response3.StatusCode} {response3.StatusCode}"); | ||
| Console.WriteLine($" Body: {await response3.Content.ReadAsStringAsync()}"); | ||
|
|
||
| await Task.Delay(500); | ||
|
|
||
| // Request 4: No matching mapping (404) | ||
| Console.WriteLine("\n>>> Request 4: GET /api/notfound"); | ||
| var response4 = await httpClient.GetAsync("/api/notfound"); | ||
| Console.WriteLine($"<<< Response: {(int)response4.StatusCode} {response4.StatusCode}"); | ||
|
|
||
| await Task.Delay(500); | ||
petrroll marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Request 5: Admin API request (should be excluded from tracing) | ||
| Console.WriteLine("\n>>> Request 5: GET /__admin/health"); | ||
| var response5 = await httpClient.GetAsync("/__admin/health"); | ||
| Console.WriteLine($"<<< Admin Health Status: {response5.StatusCode}"); | ||
|
|
||
| Console.WriteLine("\n─────────────────────────────────────────────────────────────────"); | ||
| Console.WriteLine("\nTraces above show OpenTelemetry activities from WireMock.Net!"); | ||
| Console.WriteLine("Look for 'Activity.TraceId', 'Activity.SpanId', and custom tags like:"); | ||
| Console.WriteLine(" - http.request.method"); | ||
| Console.WriteLine(" - url.path"); | ||
| Console.WriteLine(" - http.response.status_code"); | ||
| Console.WriteLine(" - wiremock.mapping.matched"); | ||
| Console.WriteLine(" - wiremock.mapping.guid"); | ||
| Console.WriteLine(); | ||
|
|
||
| // Cleanup | ||
| server.Stop(); | ||
| Console.WriteLine("WireMock server stopped. Demo complete!"); | ||
15 changes: 15 additions & 0 deletions
15
examples/WireMock.Net.OpenTelemetryDemo/WireMock.Net.OpenTelemetryDemo.csproj
This file contains hidden or 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,15 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net8.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\src\WireMock.Net.OpenTelemetry\WireMock.Net.OpenTelemetry.csproj" /> | ||
| <ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
This file contains hidden or 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 hidden or 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 hidden or 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
38 changes: 38 additions & 0 deletions
38
src/WireMock.Net.Minimal/Owin/ActivityTracing/ActivityTracingOptions.cs
This file contains hidden or 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,38 @@ | ||
| // Copyright © WireMock.Net | ||
|
|
||
| #if ACTIVITY_TRACING_SUPPORTED | ||
|
|
||
| namespace WireMock.Owin.ActivityTracing; | ||
|
|
||
| /// <summary> | ||
| /// Options for controlling activity tracing in WireMock.Net middleware. | ||
| /// These options control the creation of System.Diagnostics.Activity objects | ||
| /// but do not require any OpenTelemetry exporter dependencies. | ||
| /// </summary> | ||
| public class ActivityTracingOptions | ||
| { | ||
| /// <summary> | ||
| /// Gets or sets a value indicating whether to exclude admin interface requests from tracing. | ||
| /// Default is <c>true</c>. | ||
| /// </summary> | ||
| public bool ExcludeAdminRequests { get; set; } = true; | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether to record request body in trace attributes. | ||
| /// Default is <c>false</c> due to potential PII concerns. | ||
| /// </summary> | ||
| public bool RecordRequestBody { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether to record response body in trace attributes. | ||
| /// Default is <c>false</c> due to potential PII concerns. | ||
| /// </summary> | ||
| public bool RecordResponseBody { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Gets or sets a value indicating whether to record mapping match details in trace attributes. | ||
| /// Default is <c>true</c>. | ||
| /// </summary> | ||
| public bool RecordMatchDetails { get; set; } = true; | ||
| } | ||
| #endif |
34 changes: 34 additions & 0 deletions
34
src/WireMock.Net.Minimal/Owin/ActivityTracing/ActivityTracingValidator.cs
This file contains hidden or 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,34 @@ | ||
| // Copyright © WireMock.Net | ||
|
|
||
| #if !ACTIVITY_TRACING_SUPPORTED | ||
| using System; | ||
| #endif | ||
| using WireMock.Settings; | ||
|
|
||
| namespace WireMock.Owin.ActivityTracing; | ||
|
|
||
| /// <summary> | ||
| /// Validator for Activity Tracing configuration. | ||
| /// </summary> | ||
| internal static class ActivityTracingValidator | ||
| { | ||
| /// <summary> | ||
| /// Validates that Activity Tracing is supported on the current framework. | ||
| /// Throws an exception if ActivityTracingOptions is configured on an unsupported framework. | ||
| /// </summary> | ||
| /// <param name="settings">The WireMock server settings to validate.</param> | ||
| /// <exception cref="System.InvalidOperationException"> | ||
| /// Thrown when ActivityTracingOptions is configured but the current framework does not support System.Diagnostics.Activity. | ||
| /// </exception> | ||
| public static void ValidateActivityApiPresence(WireMockServerSettings settings) | ||
| { | ||
| #if !ACTIVITY_TRACING_SUPPORTED | ||
| if (settings.ActivityTracingOptions is not null) | ||
| { | ||
| throw new InvalidOperationException( | ||
StefH marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| "Activity Tracing is not supported on this target framework. " + | ||
| "It requires .NET 5.0 or higher which includes System.Diagnostics.Activity support."); | ||
| } | ||
| #endif | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.