diff --git a/src/Exceptionless.Web/Api/Handlers/EventHandler.cs b/src/Exceptionless.Web/Api/Handlers/EventHandler.cs index eb77c82c92..cc72b79bb2 100644 --- a/src/Exceptionless.Web/Api/Handlers/EventHandler.cs +++ b/src/Exceptionless.Web/Api/Handlers/EventHandler.cs @@ -230,7 +230,7 @@ public async Task>> Handle(GetEventsByReferenceId mes var ti = TimeRangeParser.GetTimeInfo(null, message.Offset, timeProvider, _allowedDateFields, DefaultDateField, organizations.GetRetentionUtcCutoff(appOptions.MaximumRetentionDays, timeProvider)); var sf = new AppFilter(organizations) { IsUserOrganizationsFilter = true }; - return await GetInternalAsync(sf, ti, httpContext, String.Concat("reference:", message.ReferenceId), null, message.Mode, message.Page, message.Limit, message.Before, message.After, includeTotal: ShouldIncludeTotal(message.Include)); + return await GetInternalAsync(sf, ti, httpContext, $"(reference:{message.ReferenceId} OR ref.parent:{message.ReferenceId})", null, message.Mode, message.Page, message.Limit, message.Before, message.After, includeTotal: ShouldIncludeTotal(message.Include)); } public async Task>> Handle(GetEventsByReferenceIdAndProject message) @@ -249,7 +249,7 @@ public async Task>> Handle(GetEventsByReferenceIdAndP var ti = TimeRangeParser.GetTimeInfo(null, message.Offset, timeProvider, _allowedDateFields, DefaultDateField, organization.GetRetentionUtcCutoff(project, appOptions.MaximumRetentionDays, timeProvider)); var sf = new AppFilter(project, organization); - return await GetInternalAsync(sf, ti, httpContext, String.Concat("reference:", message.ReferenceId), null, message.Mode, message.Page, message.Limit, message.Before, message.After, includeTotal: ShouldIncludeTotal(message.Include)); + return await GetInternalAsync(sf, ti, httpContext, $"(reference:{message.ReferenceId} OR ref.parent:{message.ReferenceId})", null, message.Mode, message.Page, message.Limit, message.Before, message.After, includeTotal: ShouldIncludeTotal(message.Include)); } public async Task>> Handle(GetEventsBySessionId message) diff --git a/tests/Exceptionless.Tests/Api/Endpoints/EventEndpointTests.cs b/tests/Exceptionless.Tests/Api/Endpoints/EventEndpointTests.cs index 00be49ac24..53fa1a0bf7 100644 --- a/tests/Exceptionless.Tests/Api/Endpoints/EventEndpointTests.cs +++ b/tests/Exceptionless.Tests/Api/Endpoints/EventEndpointTests.cs @@ -197,6 +197,33 @@ public async Task GetByReferenceIdAsync_WithExistingReference_ReturnsMatchingEve Assert.Equal(referenceId, ev.ReferenceId); } + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task GetByReferenceIdAsync_WithOnlyParentReference_ReturnsMatchingEvents(bool projectScoped) + { + // Arrange + string referenceId = Guid.NewGuid().ToString("N"); + await CreateDataAsync(d => d.Event().TestProject().Reference("parent", referenceId).Message("parent reference route")); + await RefreshDataAsync(); + + string[] paths = projectScoped + ? ["projects", SampleDataService.TEST_PROJECT_ID, "events", "by-ref", referenceId] + : ["events", "by-ref", referenceId]; + + // Act + var events = await SendRequestAsAsync>(r => r + .AsTestOrganizationUser() + .AppendPaths(paths) + .StatusCodeShouldBeOk() + ); + + // Assert + Assert.NotNull(events); + var ev = Assert.Single(events); + Assert.Equal(referenceId, ev.GetEventReference("parent")); + } + [Fact] public async Task GetCountByOrganizationAsync_WithExistingEvents_ReturnsOrganizationCount() { diff --git a/tests/http/events.http b/tests/http/events.http index 271fdcaaa6..e52d3c35c1 100644 --- a/tests/http/events.http +++ b/tests/http/events.http @@ -71,6 +71,14 @@ Content-Type: application/json "reference_id": "{{referenceId}}" } +### By ReferenceId +GET {{apiUrl}}/events/by-ref/{{referenceId}} +Authorization: Bearer {{token}} + +### By ReferenceId And Project +GET {{apiUrl}}/projects/{{projectId}}/events/by-ref/{{referenceId}} +Authorization: Bearer {{token}} + ### Post User Description POST {{apiUrl}}/events/by-ref/{{referenceId}}/user-description?access_token={{clientToken}} Content-Type: application/json