MetricsValues readMetricsValues()

in oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetricsQueryDAO.java [99:227]


    MetricsValues readMetricsValues(MetricsCondition condition,
                                    String valueColumnName,
                                    Duration duration) throws IOException;

    List<MetricsValues> readLabeledMetricsValues(MetricsCondition condition,
                                                 String valueColumnName,
                                                 List<KeyValue> labels,
                                                 Duration duration) throws IOException;

    /**
     * Read metrics values without entity. Used for get the labels' metadata.
     */
    List<MetricsValues> readLabeledMetricsValuesWithoutEntity(String metricName,
                                                              String valueColumnName,
                                                              List<KeyValue> labels,
                                                              Duration duration) throws IOException;

    HeatMap readHeatMap(MetricsCondition condition, String valueColumnName, Duration duration) throws IOException;

    class Util {
        /**
         * Make sure the order is same as the expected order, add defaultValue if absent.
         */
        public static IntValues sortValues(IntValues origin, List<String> expectedOrder, int defaultValue) {
            IntValues intValues = new IntValues();

            expectedOrder.forEach(id -> {
                intValues.addKVInt(origin.findValue(id, defaultValue));
            });

            return intValues;
        }

        /**
         * Make sure the order is same as the expected order, add defaultValue if absent.
         */
        public static List<MetricsValues> sortValues(List<MetricsValues> origin,
                                                     List<String> expectedOrder,
                                                     int defaultValue) {
            for (int i = 0; i < origin.size(); i++) {
                final MetricsValues metricsValues = origin.get(i);
                metricsValues.setValues(sortValues(metricsValues.getValues(), expectedOrder, defaultValue));
            }
            return origin;
        }

        /**
         * Compose the multiple metric result based on conditions.
         */
        public static List<MetricsValues> composeLabelValue(final String metricName,
                                                            final List<KeyValue> queryLabels,
                                                            final List<String> ids,
                                                            final Map<String, DataTable> idMap) {
            final Optional<ValueColumnMetadata.ValueColumn> valueColumn
                = ValueColumnMetadata.INSTANCE.readValueColumnDefinition(metricName);
            if (valueColumn.isEmpty()) {
                return Collections.emptyList();
            }
            //compatible with old version query
            if (valueColumn.get().isMultiIntValues()) {
                List<String> labelValues = buildLabelIndex(queryLabels, Const.COMMA).values()
                                                                                    .stream()
                                                                                    .flatMap(List::stream)
                                                                                    .collect(Collectors.toList());
                return composeLabelValueForMultiIntValues(metricName, labelValues, ids, idMap);
            }
            return composeLabelValueForMultipleLabels(metricName, queryLabels, ids, idMap);
        }

        public static List<String> composeLabelConditions(final List<KeyValue> queryLabels,
                                                          final Collection<DataTable> metricValues) {
            LinkedHashMap<String, List<String>> queryLabelIndex = buildLabelIndex(queryLabels, Const.COMMA);
            List<String> labelConditions = new ArrayList<>();
            if (queryLabelIndex.isEmpty()) {
                labelConditions = metricValues.stream()
                                      .flatMap(dataTable -> dataTable.keys().stream())
                                      .distinct()
                                      .filter(k -> k.startsWith(Const.LEFT_BRACE))
                                      .collect(Collectors.toList());
            } else {
                List<Set<String>> keySets = new ArrayList<>();
                for (Map.Entry<String, List<String>> queryLabel : queryLabelIndex.entrySet()) {
                    Set<String> keySet = new HashSet<>();
                    metricValues.forEach(dataTable -> {
                        var metricLabelIndex = dataTable.buildLabelIndex();
                        for (String labelValue : queryLabel.getValue()) {
                            //union labels
                            keySet.addAll(metricLabelIndex.getOrDefault(
                                queryLabel.getKey() + Const.EQUAL + labelValue,
                                new HashSet<>()
                            ));
                        }
                    });
                    if (!keySet.isEmpty()) {
                        keySets.add(keySet);
                    }
                }
                //intersection labels
                keySets.stream().reduce((a, b) -> {
                    a.retainAll(b);
                    return a;
                }).ifPresent(labelConditions::addAll);
            }
            return labelConditions;
        }

        private static List<MetricsValues> composeLabelValueForMultiIntValues(final String metricName,
            final List<String> labels,
            final List<String> ids,
            final Map<String, DataTable> idMap) {
            List<String> allLabels;
            if (Objects.isNull(labels) || labels.isEmpty() || labels.stream().allMatch(Strings::isNullOrEmpty)) {
                allLabels = idMap.values().stream()
                    .flatMap(dataTable -> dataTable.keys().stream())
                    .distinct().filter(k -> !k.startsWith(Const.LEFT_BRACE)).collect(Collectors.toList());
            } else {
                allLabels = labels;
            }
            return buildMetricsValues(metricName, ids, idMap, allLabels);
        }

        private static List<MetricsValues> composeLabelValueForMultipleLabels(final String metricName,
                                                                              final List<KeyValue> queryLabels,
                                                                              final List<String> ids,
                                                                              final Map<String, DataTable> idMap) {
            List<String> labelConditions = composeLabelConditions(queryLabels, idMap.values());
            return buildMetricsValues(metricName, ids, idMap, labelConditions);
        }
    }