in core/src/main/java/org/apache/brooklyn/util/core/logbook/file/FileLogStore.java [128:228]
public List<BrooklynLogEntry> query(LogBookQueryParams params) {
// TODO: the read of the file needs to be improved, specially to implement reading the file backwards and
// do a correct multiline log reading
try (Stream<String> stream = Files.lines(path)) {
// Only enumerate child tasks once before preparing predicate
final Set<String> childTaskIds = MutableSet.of();
if (Strings.isNonBlank(params.getTaskId()) && params.isRecursive()) {
if (mgmt != null) {
// if a requested parent task is workflow, also include the workflow ID
Task<?> parent = mgmt.getExecutionManager().getTask(params.getTaskId());
BrooklynTaskTags.WorkflowTaskTag wf = BrooklynTaskTags.getWorkflowTaskTag(parent, false);
String workflowId = wf != null ? wf.getWorkflowId() : null;
childTaskIds.addAll(enumerateTaskIds(MutableSet.of().putIfNotNull(parent).putIfNotNull(workflowId), maxTasks));
}
}
Date dateTimeFrom = Strings.isNonBlank(params.getDateTimeFrom()) ? Time.parseDate(params.getDateTimeFrom()) : null;
Date dateTimeTo = Strings.isNonBlank(params.getDateTimeTo()) ? Time.parseDate(params.getDateTimeTo()) : null;
Predicate<BrooklynLogEntry> filter = brooklynLogEntry -> {
// Excludes unrecognized items or items without a date, typically they are multiline log messages.
if (brooklynLogEntry == null || brooklynLogEntry.getDatetime() == null) {
// TODO: fix the RegEx to process multiline log messages like stack-traces, and remove this condition.
return false;
}
// Check log levels.
if (!params.getLevels().isEmpty() && !params.getLevels().contains("ALL")) {
if (!params.getLevels().contains(brooklynLogEntry.getLevel())) return false;
}
// Date-time from.
if (!Objects.isNull(dateTimeFrom)) {
if (brooklynLogEntry.getDatetime()==null || brooklynLogEntry.getDatetime().compareTo(dateTimeFrom) < 0) return false;
}
// Date-time to.
if (!Objects.isNull(dateTimeTo)) {
if (brooklynLogEntry.getDatetime()==null || brooklynLogEntry.getDatetime().compareTo(dateTimeTo) > 0) return false;
}
// Check search entityId as field or part of the message.
if (Strings.isNonBlank(params.getEntityId())) {
if ((Strings.isBlank(brooklynLogEntry.getEntityIds()) || !brooklynLogEntry.getEntityIds().contains(params.getEntityId())) &&
(Strings.isBlank(brooklynLogEntry.getMessage()) || !brooklynLogEntry.getMessage().contains(params.getEntityId()))) return false;
}
// Check search taskId as field or part of the message.
if (Strings.isNonBlank(params.getTaskId())) {
boolean isSearchTaskIdMatch = false;
isSearchTaskIdMatch =
params.getTaskId().equals(brooklynLogEntry.getTaskId()) ||
(Strings.isNonBlank(brooklynLogEntry.getMessage()) && brooklynLogEntry.getMessage().contains(params.getTaskId()));
// Check child taskIds
if (params.isRecursive() && !isSearchTaskIdMatch && !childTaskIds.isEmpty()) {
isSearchTaskIdMatch = childTaskIds.stream().anyMatch(id ->
id.equals(brooklynLogEntry.getTaskId()) ||
(Strings.isNonBlank(brooklynLogEntry.getMessage()) && brooklynLogEntry.getMessage().contains(id)));
}
if (!isSearchTaskIdMatch) return false;
}
// Check search phrases.
if (Strings.isNonBlank(params.getSearchPhrase())) {
if (Strings.isBlank(brooklynLogEntry.getMessage()) || !brooklynLogEntry.getMessage().contains(params.getSearchPhrase())) return false;
}
return true;
};
// Use line count to supply identification of go lines.
AtomicInteger lineCount = new AtomicInteger();
// Filter result first, we need to know how many to skip go get the tail.
List<BrooklynLogEntry> filteredQueryResult = stream
.map(line -> parseLogLine(line, lineCount))
.filter(filter)
.collect(Collectors.toList());
// Now get 'tail' of the filtered query, if requested, or 'head' otherwise.
Stream<BrooklynLogEntry> filteredStream;
if (params.isTail()) {
// Get 'tail' - last number of lines, with the stream().skip().
filteredStream = filteredQueryResult.stream()
.skip(Math.max(0, filteredQueryResult.size() - params.getNumberOfItems()));
} else {
// Get 'head' - first number of lines, with the stream().limit()
filteredStream = filteredQueryResult.stream().limit(params.getNumberOfItems());
}
// Collect the query result.
return filteredStream.collect(Collectors.toList());
} catch (IOException e) {
throw Exceptions.propagate(e);
}
}