Skip to content

Commit

Permalink
Improving Events Services. (#21172)
Browse files Browse the repository at this point in the history
* Widen parameter type for easier use with different collections.

* Using methods for bulk retrieval to reduce db roundtrips.

* Extracting helper function for parsing timestamp filters.

* Improving typing.

* Removing leading underscore from variables.

* Adding license header.
  • Loading branch information
dennisoelkers authored Dec 12, 2024
1 parent a4c1634 commit fad12cc
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
Expand Down Expand Up @@ -212,7 +213,7 @@ public Stream<EventDefinitionDto> streamAll() {
return stream(collection.find());
}

public List<EventDefinitionDto> getByIds(List<String> ids) {
public List<EventDefinitionDto> getByIds(Collection<String> ids) {
return MongoUtils.stream(collection.find(MongoUtils.stringIdsIn(ids)))
.map(this::getEventDefinitionWithRefetchedFilters)
.toList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.graylog.events.event.EventDto;
import org.graylog.events.processor.DBEventDefinitionService;
import org.graylog.events.processor.EventDefinitionDto;
import org.graylog2.database.NotFoundException;
import org.graylog2.indexer.IndexMapping;
import org.graylog2.plugin.database.Persisted;
import org.graylog2.plugin.indexer.searches.timeranges.TimeRange;
Expand All @@ -37,8 +36,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collector;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -231,23 +228,14 @@ private Set<String> forbiddenSourceStreams(Subject subject) {
}

private Map<String, EventsSearchResult.ContextEntity> lookupStreams(Set<String> streams) {
return streams.stream()
.map(streamId -> {
try {
return streamService.load(streamId);
} catch (NotFoundException e) {
return null;
}
})
.filter(Objects::nonNull)
return streamService.loadByIds(streams)
.stream()
.collect(Collectors.toMap(Persisted::getId, s -> EventsSearchResult.ContextEntity.create(s.getId(), s.getTitle(), s.getDescription())));
}

private Map<String, EventsSearchResult.ContextEntity> lookupEventDefinitions(Set<String> eventDefinitions) {
return eventDefinitions.stream()
.map(eventDefinitionService::get)
.filter(Optional::isPresent)
.map(Optional::get)
return eventDefinitionService.getByIds(eventDefinitions)
.stream()
.collect(Collectors.toMap(EventDefinitionDto::id,
d -> EventsSearchResult.ContextEntity.create(d.id(), d.title(), d.description(), d.remediationSteps())));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (C) 2020 Graylog, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import moment from 'moment';
import trim from 'lodash/trim';

import { extractRangeFromString } from 'components/common/EntityFilters/helpers/timeRange';
import { adjustFormat } from 'util/DateTime';
import type { TimeRange, RelativeTimeRange } from 'views/logic/queries/Query';

const allTimesRange: RelativeTimeRange = { type: 'relative', range: 0 };

const isNullOrBlank = (s: string | undefined) => {
if (!s) {
return true;
}

return trim(s) === '';
};

const parseTimerangeFilter = (timestamp: string | undefined): TimeRange => {
if (!timestamp) {
return allTimesRange;
}

const [from, to] = extractRangeFromString(timestamp);

if (!from && !to) {
return allTimesRange;
}

return {
type: 'absolute',
from: isNullOrBlank(from) ? adjustFormat(moment(0).utc(), 'internal') : from,
to: isNullOrBlank(to) ? adjustFormat(moment().utc(), 'internal') : to,
};
};

export default parseTimerangeFilter;
Original file line number Diff line number Diff line change
Expand Up @@ -110,25 +110,25 @@ export const getGeneralEventAttributeRenderers = <T extends EntityBase, M = unkn
message: {
minWidth: 300,
width: 0.5,
renderCell: (_message: string, event) => <MessageRenderer message={_message} eventId={event.id} />,
renderCell: (message: string, event) => <MessageRenderer message={message} eventId={event.id} />,
},
key: {
renderCell: (_key: string) => <span>{_key || <em>No Key set for this Event.</em>}</span>,
renderCell: (key: string) => <span>{key || <em>No Key set for this Event.</em>}</span>,
staticWidth: 200,
},
id: {
staticWidth: 300,
},
alert: {
renderCell: (_alert: boolean) => <EventTypeLabel isAlert={_alert} />,
renderCell: (alert: boolean) => <EventTypeLabel isAlert={alert} />,
staticWidth: 100,
},
priority: {
renderCell: (_priority: number) => <PriorityName priority={_priority} />,
renderCell: (priority: number) => <PriorityName priority={priority} />,
staticWidth: 100,
},
event_definition_type: {
renderCell: (_type: string) => <EventDefinitionTypeRenderer type={_type} />,
renderCell: (type: string) => <EventDefinitionTypeRenderer type={type} />,
staticWidth: 200,
},
group_by_fields: {
Expand All @@ -142,10 +142,10 @@ const customColumnRenderers = (): ColumnRenderers<Event> => ({
event_definition_id: {
minWidth: 300,
width: 0.3,
renderCell: (_eventDefinitionId: string, _, __, meta: EventsAdditionalData) => <EventDefinitionRenderer meta={meta} eventDefinitionId={_eventDefinitionId} />,
renderCell: (eventDefinitionId: string, _, __, meta: EventsAdditionalData) => <EventDefinitionRenderer meta={meta} eventDefinitionId={eventDefinitionId} />,
},
fields: {
renderCell: (_fields: Record<string, string>) => <FieldsRenderer fields={_fields} />,
renderCell: (fields: Record<string, string>) => <FieldsRenderer fields={fields} />,
staticWidth: 400,
},
remediation_steps: {
Expand Down
39 changes: 4 additions & 35 deletions graylog2-web-interface/src/components/events/fetchEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*/

import moment from 'moment';
import trim from 'lodash/trim';

import * as URLUtils from 'util/URLUtils';
import { adjustFormat } from 'util/DateTime';
Expand All @@ -27,6 +26,8 @@ import type { Event, EventsAdditionalData } from 'components/events/events/types
import { additionalAttributes } from 'components/events/Constants';
import { extractRangeFromString } from 'components/common/EntityFilters/helpers/timeRange';
import type { UrlQueryFilters } from 'components/common/EntityFilters/types';
import parseTimerangeFilter from 'components/common/PaginatedEntityTable/parseTimerangeFilter';
import type { TimeRange } from 'views/logic/queries/Query';

const url = URLUtils.qualifyUrl('/events/search');

Expand All @@ -38,39 +39,7 @@ type FiltersResult = {
aggregation_timerange?: { from?: string, to?: string, type: string, range?: number },
key?: Array<string>,
},
timerange?: { from?: string, to?: string, type: string, range?: number },
};

const allTimesRange = { type: 'relative', range: 0 };

const isNullOrBlank = (s: string | undefined) => {
if (!s) {
return true;
}

if (trim(s) === '') {
return true;
}

return false;
};

const parseTimestampFilter = (timestamp: string | undefined) => {
if (!timestamp) {
return allTimesRange;
}

const [from, to] = extractRangeFromString(timestamp);

if (!from && !to) {
return allTimesRange;
}

return {
type: 'absolute',
from: isNullOrBlank(from) ? adjustFormat(moment(0).utc(), 'internal') : from,
to: isNullOrBlank(to) ? adjustFormat(moment().utc(), 'internal') : to,
};
timerange?: TimeRange,
};

export const parseTypeFilter = (alert: string) => {
Expand All @@ -87,7 +56,7 @@ export const parseTypeFilter = (alert: string) => {
const parseFilters = (filters: UrlQueryFilters) => {
const result: FiltersResult = { filter: {} };

result.timerange = parseTimestampFilter(filters.get('timestamp')?.[0]);
result.timerange = parseTimerangeFilter(filters.get('timestamp')?.[0]);

if (filters.get('timerange_start')?.[0]) {
const [from, to] = extractRangeFromString(filters.get('timerange_start')[0]);
Expand Down

0 comments on commit fad12cc

Please sign in to comment.