mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-28 17:55:15 +02:00
feat: now it is possible to search events by group id (#10275)
Now when you put group ID as query param, it will filter based on transaction id. I am not sure if its best naming, whether it should be groupId or transactionId, I will leave as group for now, but its simple change later. 
This commit is contained in:
parent
a251a9808a
commit
7e85de8f65
@ -73,6 +73,7 @@ export const useEventLogSearch = (
|
|||||||
type: FilterItemParam,
|
type: FilterItemParam,
|
||||||
environment: FilterItemParam,
|
environment: FilterItemParam,
|
||||||
id: StringParam,
|
id: StringParam,
|
||||||
|
groupId: StringParam,
|
||||||
...extraParameters(logType),
|
...extraParameters(logType),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -222,6 +222,11 @@ export default class EventService {
|
|||||||
if (parsed) queryParams.push(parsed);
|
if (parsed) queryParams.push(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.groupId) {
|
||||||
|
const parsed = parseSearchOperatorValue('group_id', params.groupId);
|
||||||
|
if (parsed) queryParams.push(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
['project', 'type', 'environment', 'id'].forEach((field) => {
|
['project', 'type', 'environment', 'id'].forEach((field) => {
|
||||||
if (params[field]) {
|
if (params[field]) {
|
||||||
const parsed = parseSearchOperatorValue(field, params[field]);
|
const parsed = parseSearchOperatorValue(field, params[field]);
|
||||||
|
@ -22,6 +22,17 @@ export const eventSearchQueryParameters = [
|
|||||||
'Filter by event ID using supported operators: IS, IS_ANY_OF.',
|
'Filter by event ID using supported operators: IS, IS_ANY_OF.',
|
||||||
in: 'query',
|
in: 'query',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'groupId',
|
||||||
|
schema: {
|
||||||
|
type: 'string',
|
||||||
|
example: 'IS:123',
|
||||||
|
pattern: '^(IS|IS_ANY_OF):(.*?)(,([0-9]+))*$',
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
'Filter by group ID using supported operators: IS, IS_ANY_OF.',
|
||||||
|
in: 'query',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'feature',
|
name: 'feature',
|
||||||
schema: {
|
schema: {
|
||||||
|
@ -7,6 +7,7 @@ import type { IQueryParam } from '../../features/feature-toggle/types/feature-to
|
|||||||
|
|
||||||
export interface IEventSearchParams {
|
export interface IEventSearchParams {
|
||||||
id?: string;
|
id?: string;
|
||||||
|
groupId?: string;
|
||||||
project?: string;
|
project?: string;
|
||||||
query?: string;
|
query?: string;
|
||||||
feature?: string;
|
feature?: string;
|
||||||
|
@ -16,6 +16,8 @@ import {
|
|||||||
import { createEventsService } from '../../../../lib/features/index.js';
|
import { createEventsService } from '../../../../lib/features/index.js';
|
||||||
import { createTestConfig } from '../../../config/test-config.js';
|
import { createTestConfig } from '../../../config/test-config.js';
|
||||||
import { FEATURE_CREATED, USER_CREATED } from '../../../../lib/events/index.js';
|
import { FEATURE_CREATED, USER_CREATED } from '../../../../lib/events/index.js';
|
||||||
|
import { withTransactional } from '../../../../lib/db/transaction.js';
|
||||||
|
import { EventStore } from '../../../../lib/features/events/event-store.js';
|
||||||
|
|
||||||
let app: IUnleashTest;
|
let app: IUnleashTest;
|
||||||
let db: ITestDb;
|
let db: ITestDb;
|
||||||
@ -718,3 +720,140 @@ test('should filter events by multiple IDs using IS_ANY_OF', async () => {
|
|||||||
);
|
);
|
||||||
expect(returnedIds).not.toContain(feature2Event.id);
|
expect(returnedIds).not.toContain(feature2Event.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should filter events by group ID', async () => {
|
||||||
|
const eventStoreService = withTransactional(
|
||||||
|
(db) => new EventStore(db, getLogger),
|
||||||
|
db.rawDatabase,
|
||||||
|
);
|
||||||
|
|
||||||
|
const events = [
|
||||||
|
{
|
||||||
|
type: FEATURE_CREATED,
|
||||||
|
project: 'default',
|
||||||
|
data: { name: 'feature1' },
|
||||||
|
createdBy: 'test-user',
|
||||||
|
createdByUserId: TEST_USER_ID,
|
||||||
|
ip: '127.0.0.1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: FEATURE_CREATED,
|
||||||
|
project: 'default',
|
||||||
|
data: { name: 'feature2' },
|
||||||
|
createdBy: 'test-user',
|
||||||
|
createdByUserId: TEST_USER_ID,
|
||||||
|
ip: '127.0.0.1',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
await eventStoreService.transactional(
|
||||||
|
async (transactionalEventStore) => {
|
||||||
|
await transactionalEventStore.batchStore(events);
|
||||||
|
},
|
||||||
|
{ type: 'transaction', id: '1' },
|
||||||
|
);
|
||||||
|
|
||||||
|
await eventService.storeEvent({
|
||||||
|
type: FEATURE_CREATED,
|
||||||
|
project: 'default',
|
||||||
|
data: { name: 'feature3' },
|
||||||
|
createdBy: 'test-user',
|
||||||
|
createdByUserId: TEST_USER_ID,
|
||||||
|
ip: '127.0.0.1',
|
||||||
|
});
|
||||||
|
|
||||||
|
const { body } = await searchEvents({ groupId: 'IS:1' });
|
||||||
|
|
||||||
|
expect(body.total).toBe(2);
|
||||||
|
expect(body.events).toHaveLength(2);
|
||||||
|
expect(body.events.every((e: any) => e.groupId === '1')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should filter events by multiple group IDs using IS_ANY_OF', async () => {
|
||||||
|
const eventStoreService = withTransactional(
|
||||||
|
(db) => new EventStore(db, getLogger),
|
||||||
|
db.rawDatabase,
|
||||||
|
);
|
||||||
|
|
||||||
|
const event1 = {
|
||||||
|
type: FEATURE_CREATED,
|
||||||
|
project: 'default',
|
||||||
|
data: { name: 'feature1' },
|
||||||
|
createdBy: 'test-user',
|
||||||
|
createdByUserId: TEST_USER_ID,
|
||||||
|
ip: '127.0.0.1',
|
||||||
|
};
|
||||||
|
const event2 = {
|
||||||
|
type: FEATURE_CREATED,
|
||||||
|
project: 'default',
|
||||||
|
data: { name: 'feature2' },
|
||||||
|
createdBy: 'test-user',
|
||||||
|
createdByUserId: TEST_USER_ID,
|
||||||
|
ip: '127.0.0.1',
|
||||||
|
};
|
||||||
|
const event3 = {
|
||||||
|
type: FEATURE_CREATED,
|
||||||
|
project: 'default',
|
||||||
|
data: { name: 'feature3' },
|
||||||
|
createdBy: 'test-user',
|
||||||
|
createdByUserId: TEST_USER_ID,
|
||||||
|
ip: '127.0.0.1',
|
||||||
|
};
|
||||||
|
|
||||||
|
await eventStoreService.transactional(
|
||||||
|
async (transactionalEventStore) => {
|
||||||
|
await transactionalEventStore.store(event1);
|
||||||
|
},
|
||||||
|
{ type: 'transaction', id: '10' },
|
||||||
|
);
|
||||||
|
|
||||||
|
await eventStoreService.transactional(
|
||||||
|
async (transactionalEventStore) => {
|
||||||
|
await transactionalEventStore.store(event2);
|
||||||
|
},
|
||||||
|
{ type: 'transaction', id: '20' },
|
||||||
|
);
|
||||||
|
|
||||||
|
await eventStoreService.transactional(
|
||||||
|
async (transactionalEventStore) => {
|
||||||
|
await transactionalEventStore.store(event3);
|
||||||
|
},
|
||||||
|
{ type: 'transaction', id: '30' },
|
||||||
|
);
|
||||||
|
|
||||||
|
const { body } = await searchEvents({ groupId: 'IS_ANY_OF:10,30' });
|
||||||
|
|
||||||
|
expect(body.total).toBe(2);
|
||||||
|
expect(body.events).toHaveLength(2);
|
||||||
|
|
||||||
|
const returnedGroupIds = body.events.map((e: any) => e.groupId);
|
||||||
|
expect(returnedGroupIds).toContain('10');
|
||||||
|
expect(returnedGroupIds).toContain('30');
|
||||||
|
expect(returnedGroupIds).not.toContain('20');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should return empty result when filtering by non-existent group ID', async () => {
|
||||||
|
const eventStoreService = withTransactional(
|
||||||
|
(db) => new EventStore(db, getLogger),
|
||||||
|
db.rawDatabase,
|
||||||
|
);
|
||||||
|
|
||||||
|
await eventStoreService.transactional(
|
||||||
|
async (transactionalEventStore) => {
|
||||||
|
await transactionalEventStore.store({
|
||||||
|
type: FEATURE_CREATED,
|
||||||
|
project: 'default',
|
||||||
|
data: { name: 'feature1' },
|
||||||
|
createdBy: 'test-user',
|
||||||
|
createdByUserId: TEST_USER_ID,
|
||||||
|
ip: '127.0.0.1',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ type: 'transaction', id: '1' },
|
||||||
|
);
|
||||||
|
|
||||||
|
const { body } = await searchEvents({ groupId: 'IS:999' });
|
||||||
|
|
||||||
|
expect(body.total).toBe(0);
|
||||||
|
expect(body.events).toHaveLength(0);
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user