public List query()

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);
        }
    }