diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d62a227f1..cd0bf6d69 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -76,7 +76,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Generate certificates run: | mkdir -p certs @@ -89,7 +89,7 @@ jobs: sudo chown -R $USER:$USER certs sudo chmod -R 755 certs - name: Upload certificates - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: certs path: certs @@ -123,7 +123,7 @@ jobs: run: | dotnet build --configuration ${{ matrix.configuration }} --framework ${{ matrix.framework }} src/EventStore.Client - name: Download certificates - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: certs path: certs @@ -191,7 +191,7 @@ jobs: /p:RepositoryUrl=https://github.com/EventStore/EventStore-Client-Dotnet \ /p:RepositoryType=git - name: Publish Artifacts - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: path: packages name: nuget-packages diff --git a/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs b/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs index 26bd00b44..28d336a85 100644 --- a/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs +++ b/src/EventStore.Client/Common/Diagnostics/ActivitySourceExtensions.cs @@ -1,3 +1,5 @@ +// ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + using System.Diagnostics; using EventStore.Diagnostics; using EventStore.Diagnostics.Telemetry; @@ -32,7 +34,7 @@ public static void TraceSubscriptionEvent( EventStoreClientSettings settings, UserCredentials? userCredentials ) { - if (source.HasNoActiveListeners()) + if (source.HasNoActiveListeners() || resolvedEvent.Event is null) return; var parentContext = resolvedEvent.Event.Metadata.ExtractPropagationContext(); diff --git a/src/EventStore.Client/EventStore.Client.csproj b/src/EventStore.Client/EventStore.Client.csproj index 321f89c8c..47a116602 100644 --- a/src/EventStore.Client/EventStore.Client.csproj +++ b/src/EventStore.Client/EventStore.Client.csproj @@ -14,7 +14,7 @@ - + diff --git a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs b/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs index 4c23bfffa..5a19c6b0d 100644 --- a/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs +++ b/test/EventStore.Client.Streams.Tests/Diagnostics/StreamsTracingInstrumentationTests.cs @@ -1,3 +1,5 @@ +// ReSharper disable ConditionalAccessQualifierIsNonNullableAccordingToAPIContract + using EventStore.Client.Diagnostics; using EventStore.Diagnostics.Tracing; @@ -171,4 +173,49 @@ async Task Subscribe(IAsyncEnumerator internalEnumerator) { } } } + + [Fact] + [Trait("Category", "Special cases")] + public async Task should_not_trace_when_event_is_null() { + var category = Guid.NewGuid().ToString("N"); + var streamName = category + "-123"; + + var seedEvents = Fixture.CreateTestEvents(type: $"{category}-{Fixture.GetStreamName()}").ToArray(); + await Fixture.Streams.AppendToStreamAsync(streamName, StreamState.NoStream, seedEvents); + + await Fixture.Streams.DeleteAsync(streamName, StreamState.StreamExists); + + await using var subscription = Fixture.Streams.SubscribeToStream("$ce-" + category, FromStream.Start, resolveLinkTos: true); + + await using var enumerator = subscription.Messages.GetAsyncEnumerator(); + + Assert.True(await enumerator.MoveNextAsync()); + + Assert.IsType(enumerator.Current); + + await Subscribe().WithTimeout(); + + var appendActivities = Fixture + .GetActivitiesForOperation(TracingConstants.Operations.Append, streamName) + .ShouldNotBeNull(); + + var subscribeActivities = Fixture + .GetActivitiesForOperation(TracingConstants.Operations.Subscribe, "$ce-" + category) + .ToArray(); + + appendActivities.ShouldHaveSingleItem(); + subscribeActivities.ShouldBeEmpty(); + + return; + + async Task Subscribe() { + while (await enumerator.MoveNextAsync()) { + if (enumerator.Current is not StreamMessage.Event(var resolvedEvent)) + continue; + + if (resolvedEvent.Event?.EventType is "$metadata") + return; + } + } + } } diff --git a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs b/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs index f8cd5913b..549093654 100644 --- a/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs +++ b/test/EventStore.Client.Tests.Common/Fixtures/DiagnosticsFixture.cs @@ -11,7 +11,7 @@ namespace EventStore.Client.Tests; public class DiagnosticsFixture : EventStoreFixture { readonly ConcurrentDictionary<(string Operation, string Stream), List> _activities = []; - public DiagnosticsFixture() { + public DiagnosticsFixture() : base(x => x.RunProjections()) { var diagnosticActivityListener = new ActivityListener { ShouldListenTo = source => source.Name == EventStoreClientDiagnostics.InstrumentationName, Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded,