public CompletableFuture<HeatMap> readHeatMap(MetricsCondition condition, Duration duration) {
        return queryAsync(() -> {
            boolean hasScope = condition.senseScope();
            if (!hasScope || !condition.getEntity().isValid()) {
                DataTable emptyData = new DataTable();
                emptyData.put("0", 0L);
                final String rawdata = emptyData.toStorageData();
                final HeatMap heatMap = new HeatMap();
                final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
                String entityId = "UNKNOWN_METRIC_NAME";
                if (hasScope) {
                    entityId = "ILLEGAL_ENTITY";
                }
                for (PointOfTime pointOfTime : pointOfTimes) {
                    String id = pointOfTime.id(entityId);
                    heatMap.buildColumn(id, rawdata, 0);
                }
                return heatMap;
            }
            return getMetricsQueryService().readHeatMap(condition, duration);
        });
    }
Heatmap is bucket based value statistic result.

@return heapmap including the latency distribution {@link HeatMap#getBuckets()} {@link
HeatMap.HeatMapColumn#getValues()} follows this rule.
<pre>
     key = 0, represents [0, 100), value = count of requests in the latency range.
     key = 100, represents [100, 200), value = count of requests in the latency range.
     ...
     key = step * maxNumOfSteps, represents [step * maxNumOfSteps, MAX)
</pre>
oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/MetricsQuery.java