You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ha...@apache.org on 2020/07/27 23:07:39 UTC

[skywalking] branch meter-label created (now 4e1008e)

This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a change to branch meter-label
in repository https://gitbox.apache.org/repos/asf/skywalking.git.


      at 4e1008e  Add AvgLabeledFunction to ingest multiple labels

This branch includes the following new commits:

     new 4e1008e  Add AvgLabeledFunction to ingest multiple labels

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[skywalking] 01/01: Add AvgLabeledFunction to ingest multiple labels

Posted by ha...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a commit to branch meter-label
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit 4e1008ee2884711fdf2e75038ada9c87e73bd051
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Tue Jul 28 06:55:50 2020 +0800

    Add AvgLabeledFunction to ingest multiple labels
---
 .../meter/function/AvgLabeledFunction.java         | 215 +++++++++++++++++++++
 .../promethues/PrometheusMetricConverter.java      |  38 +++-
 .../metric/promethues/operation/MetricSource.java  |   3 +
 .../metric/promethues/rule/PrometheusMetric.java   |   1 +
 .../server/core/metric/promethues/rule/Rules.java  |   1 +
 .../meter/function/AvgLabeledFunctionTest.java     | 112 +++++++++++
 .../provider/PrometheusFetcherProvider.java        |   3 +
 7 files changed, 369 insertions(+), 4 deletions(-)

diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgLabeledFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgLabeledFunction.java
new file mode 100644
index 0000000..a8b9ad1
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgLabeledFunction.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.analysis.meter.function;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.UnexpectedException;
+import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
+import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
+import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
+import org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData;
+import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
+import org.apache.skywalking.oap.server.core.storage.annotation.Column;
+
+@MeterFunction(functionName = "avgLabeled")
+@ToString
+public abstract class AvgLabeledFunction extends Metrics implements AcceptableValue<DataTable> {
+    protected static final String SUMMATION = "summation";
+    protected static final String COUNT = "count";
+    protected static final String VALUE = "value";
+
+    @Setter
+    @Getter
+    @Column(columnName = ENTITY_ID, length = 512)
+    private String entityId;
+
+    /**
+     * Service ID is required for sort query.
+     */
+    @Setter
+    @Getter
+    @Column(columnName = InstanceTraffic.SERVICE_ID)
+    private String serviceId;
+
+    @Getter
+    @Setter
+    @Column(columnName = SUMMATION, storageOnly = true)
+    protected DataTable summation = new DataTable(30);
+    @Getter
+    @Setter
+    @Column(columnName = COUNT, storageOnly = true)
+    protected DataTable count = new DataTable(30);
+    @Getter
+    @Setter
+    @Column(columnName = VALUE, dataType = Column.ValueDataType.LABELED_VALUE, storageOnly = true)
+    private DataTable value = new DataTable(30);
+
+    @Override
+    public final void combine(Metrics metrics) {
+        AvgLabeledFunction longAvgMetrics = (AvgLabeledFunction) metrics;
+        summation.append(longAvgMetrics.summation);
+        count.append(longAvgMetrics.count);
+    }
+
+    @Override
+    public final void calculate() {
+        List<String> keys = count.sortedKeys(Comparator.naturalOrder());
+        for (String key : keys) {
+            Long s = summation.get(key);
+            if (Objects.isNull(s)) {
+                continue;
+            }
+            Long c = count.get(key);
+            if (Objects.isNull(c)) {
+                continue;
+            }
+            long result = s / c;
+            if (result == 0 && s > 0) {
+                result = 1;
+            }
+            value.put(key, result);
+        }
+    }
+
+    @Override
+    public Metrics toHour() {
+        AvgLabeledFunction metrics = (AvgLabeledFunction) createNew();
+        metrics.setEntityId(getEntityId());
+        metrics.setTimeBucket(toTimeBucketInHour());
+        metrics.setServiceId(getServiceId());
+        metrics.setSummation(getSummation());
+        metrics.setCount(getCount());
+        return metrics;
+    }
+
+    @Override
+    public Metrics toDay() {
+        AvgLabeledFunction metrics = (AvgLabeledFunction) createNew();
+        metrics.setEntityId(getEntityId());
+        metrics.setTimeBucket(toTimeBucketInDay());
+        metrics.setServiceId(getServiceId());
+        metrics.setSummation(getSummation());
+        metrics.setCount(getCount());
+        return metrics;
+    }
+
+    @Override
+    public int remoteHashCode() {
+        return entityId.hashCode();
+    }
+
+    @Override
+    public void deserialize(final RemoteData remoteData) {
+        this.setCount(new DataTable(remoteData.getDataObjectStrings(0)));
+        this.setSummation(new DataTable(remoteData.getDataObjectStrings(1)));
+        setTimeBucket(remoteData.getDataLongs(0));
+
+        this.entityId = remoteData.getDataStrings(0);
+        this.serviceId = remoteData.getDataStrings(1);
+    }
+
+    @Override
+    public RemoteData.Builder serialize() {
+        RemoteData.Builder remoteBuilder = RemoteData.newBuilder();
+        remoteBuilder.addDataObjectStrings(count.toStorageData());
+        remoteBuilder.addDataObjectStrings(summation.toStorageData());
+        remoteBuilder.addDataLongs(getTimeBucket());
+
+        remoteBuilder.addDataStrings(entityId);
+        remoteBuilder.addDataStrings(serviceId);
+
+        return remoteBuilder;
+    }
+
+    @Override
+    public String id() {
+        return getTimeBucket() + Const.ID_CONNECTOR + entityId;
+    }
+
+    @Override
+    public void accept(final MeterEntity entity, final DataTable value) {
+        this.entityId = entity.id();
+        this.serviceId = entity.serviceId();
+        this.summation.append(value);
+        DataTable c = new DataTable();
+        value.sortedKeys(Comparator.naturalOrder()).forEach(key -> c.put(key, 1L));
+        this.count.append(c);
+    }
+
+    @Override
+    public Class<? extends AvgLabeledStorageBuilder> builder() {
+        return AvgLabeledStorageBuilder.class;
+    }
+
+    public static class AvgLabeledStorageBuilder implements StorageBuilder<AvgLabeledFunction> {
+        @Override
+        public AvgLabeledFunction map2Data(final Map<String, Object> dbMap) {
+            AvgLabeledFunction metrics = new AvgLabeledFunction() {
+                @Override
+                public AcceptableValue<DataTable> createNew() {
+                    throw new UnexpectedException("createNew should not be called");
+                }
+            };
+            metrics.setSummation(new DataTable((String) dbMap.get(SUMMATION)));
+            metrics.setValue(new DataTable((String) dbMap.get(VALUE)));
+            metrics.setCount(new DataTable((String) dbMap.get(COUNT)));
+            metrics.setTimeBucket(((Number) dbMap.get(TIME_BUCKET)).longValue());
+            metrics.setServiceId((String) dbMap.get(InstanceTraffic.SERVICE_ID));
+            metrics.setEntityId((String) dbMap.get(ENTITY_ID));
+            return metrics;
+        }
+
+        @Override
+        public Map<String, Object> data2Map(final AvgLabeledFunction storageData) {
+            Map<String, Object> map = new HashMap<>();
+            map.put(SUMMATION, storageData.getSummation());
+            map.put(VALUE, storageData.getValue());
+            map.put(COUNT, storageData.getCount());
+            map.put(TIME_BUCKET, storageData.getTimeBucket());
+            map.put(InstanceTraffic.SERVICE_ID, storageData.getServiceId());
+            map.put(ENTITY_ID, storageData.getEntityId());
+            return map;
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o)
+            return true;
+        if (!(o instanceof AvgLabeledFunction))
+            return false;
+        AvgLabeledFunction function = (AvgLabeledFunction) o;
+        return Objects.equals(entityId, function.entityId) &&
+            getTimeBucket() == function.getTimeBucket();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(entityId, getTimeBucket());
+    }
+}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java
index 8e50f50..c564c1a 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java
@@ -18,6 +18,7 @@
 
 package org.apache.skywalking.oap.server.core.metric.promethues;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableMap;
 import io.vavr.Function1;
@@ -25,6 +26,7 @@ import io.vavr.Tuple;
 import io.vavr.Tuple3;
 import io.vavr.control.Try;
 import java.math.BigDecimal;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
@@ -45,6 +47,7 @@ import org.apache.skywalking.oap.server.core.analysis.meter.MeterSystem;
 import org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
 import org.apache.skywalking.oap.server.core.analysis.meter.function.AvgHistogramPercentileFunction;
 import org.apache.skywalking.oap.server.core.analysis.meter.function.BucketedValues;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
 import org.apache.skywalking.oap.server.core.metric.promethues.counter.Window;
 import org.apache.skywalking.oap.server.core.metric.promethues.operation.MetricSource;
@@ -71,6 +74,8 @@ public class PrometheusMetricConverter {
 
     private final static String AVG = "avg";
 
+    private final static String AVG_LABELED = "avgLabeled";
+
     private final Window window = new Window();
 
     private final List<MetricsRule> rules;
@@ -132,6 +137,7 @@ public class PrometheusMetricConverter {
                     .timestamp(tuple._4.getTimestamp())
                     .scale(tuple._3.getScale())
                     .counterFunction(tuple._3.getCounterFunction())
+                    .groupBy(tuple._3.getGroupBy())
                     .range(tuple._3.getRange());
                 switch (tuple._1.getScope()) {
                     case SERVICE:
@@ -155,10 +161,23 @@ public class PrometheusMetricConverter {
                         case AVG:
                             sources.forEach((source, metrics) -> {
                                 AcceptableValue<Long> value = service.buildMetrics(formatMetricName(operation.getMetricName()), Long.class);
-                                Double sumDouble = sum(metrics).value();
-                                sumDouble = window.get(source.getPromMetricName()).apply(source, sumDouble);
-                                value.accept(source.getEntity(), BigDecimal.valueOf(Double.isNaN(sumDouble) ? 0D : sumDouble)
-                                    .multiply(BigDecimal.TEN.pow(source.getScale())).longValue());
+                                value.accept(source.getEntity(), sum(metrics, source));
+                                value.setTimeBucket(TimeBucket.getMinuteTimeBucket(source.getTimestamp()));
+                                log.debug("Input metric {}", value.getTimeBucket());
+                                service.doStreamingCalculation(value);
+
+                                generateTraffic(source.getEntity());
+                            });
+                            break;
+                        case AVG_LABELED:
+                            sources.forEach((source, metrics) -> {
+                                Preconditions.checkArgument(Objects.nonNull(source.getGroupBy()));
+                                DataTable dt = new DataTable();
+                                metrics.stream()
+                                    .collect(groupingBy(m -> source.getGroupBy().stream().map(m.getLabels()::get).collect(Collectors.joining("-"))))
+                                    .forEach((group, mm) -> dt.put(group, sum(mm, source, ImmutableMap.of("group", group))));
+                                AcceptableValue<DataTable> value = service.buildMetrics(formatMetricName(operation.getMetricName()), DataTable.class);
+                                value.accept(source.getEntity(), dt);
                                 value.setTimeBucket(TimeBucket.getMinuteTimeBucket(source.getTimestamp()));
                                 log.debug("Input metric {}", value.getTimeBucket());
                                 service.doStreamingCalculation(value);
@@ -228,6 +247,17 @@ public class PrometheusMetricConverter {
         return metrics.stream().reduce(Metric::sum).orElseThrow(IllegalArgumentException::new);
     }
 
+    private long sum(List<Metric> metrics, MetricSource source) {
+        return sum(metrics, source, Collections.emptyMap());
+    }
+
+    private long sum(List<Metric> metrics, MetricSource source, Map<String, String> labels) {
+        Double sumDouble = sum(metrics).value();
+        sumDouble = window.get(source.getPromMetricName(), labels).apply(source, sumDouble);
+        return BigDecimal.valueOf(Double.isNaN(sumDouble) ? 0D : sumDouble)
+            .multiply(BigDecimal.TEN.pow(source.getScale())).longValue();
+    }
+
     private void generateTraffic(MeterEntity entity) {
         ServiceTraffic s = new ServiceTraffic();
         s.setName(requireNonNull(entity.getServiceName()));
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/MetricSource.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/MetricSource.java
index ed503a2..983077b 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/MetricSource.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/MetricSource.java
@@ -18,6 +18,7 @@
 
 package org.apache.skywalking.oap.server.core.metric.promethues.operation;
 
+import java.util.List;
 import lombok.Builder;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
@@ -41,4 +42,6 @@ public class MetricSource {
     private final String range;
 
     private final int scale;
+
+    private final List<String> groupBy;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/PrometheusMetric.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/PrometheusMetric.java
index f02baee..4c5cdd0 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/PrometheusMetric.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/PrometheusMetric.java
@@ -28,6 +28,7 @@ public class PrometheusMetric {
     private CounterFunction counterFunction;
     private String range;
     private List<LabelMatchRule> labelFilter;
+    private List<String> groupBy;
     private Relabel relabel;
     private int scale = 0;
 }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/Rules.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/Rules.java
index 6e39e72..91537c4 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/Rules.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/Rules.java
@@ -44,6 +44,7 @@ public class Rules {
             throw new ModuleStartException("Load fetcher rules failed", e);
         }
         return Arrays.stream(rules)
+            .filter(File::isFile)
             .map(f -> {
                 try (Reader r = new FileReader(f)) {
                     Rule rule = new Yaml().loadAs(r, Rule.class);
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgLabeledFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgLabeledFunctionTest.java
new file mode 100644
index 0000000..df1fbe0
--- /dev/null
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgLabeledFunctionTest.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.oap.server.core.analysis.meter.function;
+
+import io.vavr.collection.Stream;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
+import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.apache.skywalking.oap.server.core.analysis.meter.function.AvgLabeledFunction.COUNT;
+import static org.apache.skywalking.oap.server.core.analysis.meter.function.AvgLabeledFunction.SUMMATION;
+import static org.apache.skywalking.oap.server.core.analysis.meter.function.AvgLabeledFunction.VALUE;
+import static org.hamcrest.core.Is.is;
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertThat;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AvgLabeledFunctionTest {
+    @Spy
+    private AvgLabeledFunction function;
+
+    @Test
+    public void testAccept() {
+        function.accept(MeterEntity.newService("request_count"), build(asList("200", "404"), asList(10L, 2L)));
+        assertResult(asList("200", "404"), asList(10L, 2L), asList(1L, 1L));
+        function.accept(MeterEntity.newService("request_count"), build(asList("200", "500"), asList(2L, 3L)));
+        assertResult(asList("200", "404", "500"), asList(12L, 2L, 3L), asList(2L, 1L, 1L));
+    }
+
+    @Test
+    public void testCalculate() {
+        function.accept(MeterEntity.newService("request_count"), build(asList("200", "404"), asList(10L, 2L)));
+        function.accept(MeterEntity.newService("request_count"), build(asList("200", "500"), asList(2L, 3L)));
+        function.calculate();
+
+        assertThat(function.getValue().sortedKeys(Comparator.naturalOrder()), is(asList("200", "404", "500")));
+        assertThat(function.getValue().sortedValues(Comparator.naturalOrder()), is(asList(6L, 2L, 3L)));
+    }
+
+    @Test
+    public void testSerialize() {
+        function.accept(MeterEntity.newService("request_count"), build(asList("200", "404"), asList(10L, 2L)));
+        AvgLabeledFunction function2 = Mockito.spy(AvgLabeledFunction.class);
+        function2.deserialize(function.serialize().build());
+        assertThat(function2.getEntityId(), is(function.getEntityId()));
+        assertThat(function2.getTimeBucket(), is(function.getTimeBucket()));
+    }
+
+    @Test
+    public void testBuilder() throws IllegalAccessException, InstantiationException {
+        function.accept(MeterEntity.newService("request_count"), build(asList("200", "404"), asList(10L, 2L)));
+        function.calculate();
+        StorageBuilder<AvgLabeledFunction> storageBuilder = function.builder().newInstance();
+
+        Map<String, Object> map = storageBuilder.data2Map(function);
+        map.put(SUMMATION, ((DataTable) map.get(SUMMATION)).toStorageData());
+        map.put(COUNT, ((DataTable) map.get(COUNT)).toStorageData());
+        map.put(VALUE, ((DataTable) map.get(VALUE)).toStorageData());
+
+        AvgLabeledFunction function2 = storageBuilder.map2Data(map);
+        assertThat(function2.getValue(), is(function.getValue()));
+    }
+
+    private DataTable build(List<String> keys, List<Long> values) {
+        DataTable result = new DataTable();
+        Stream.ofAll(keys).forEachWithIndex((key, i) -> result.put(key, values.get(i)));
+        return result;
+    }
+
+    private void assertResult(List<String> expectedKeys, List<Long> expectedValues, List<Long> expectedCount) {
+        assertSummation(expectedKeys, expectedValues);
+        assertCount(expectedKeys, expectedCount);
+    }
+
+    private void assertCount(List<String> expectedKeys, List<Long> expectedCount) {
+        List<String> keys = function.getCount().sortedKeys(Comparator.comparingInt(Integer::parseInt));
+        assertThat(keys, is(expectedKeys));
+        List<Long> values = function.getCount().sortedValues(Comparator.comparingLong(Long::parseLong));
+        assertThat(values, is(expectedCount));
+    }
+
+    private void assertSummation(List<String> expectedKeys, List<Long> expectedValues) {
+        List<String> keys = function.getSummation().sortedKeys(Comparator.comparingInt(Integer::parseInt));
+        assertThat(keys, is(expectedKeys));
+        List<Long> values = function.getSummation().sortedValues(Comparator.comparingLong(Long::parseLong));
+        assertThat(values, is(expectedValues));
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-fetcher-plugin/prometheus-fetcher-plugin/src/main/java/org/apache/skywalking/oap/server/fetcher/prometheus/provider/PrometheusFetcherProvider.java b/oap-server/server-fetcher-plugin/prometheus-fetcher-plugin/src/main/java/org/apache/skywalking/oap/server/fetcher/prometheus/provider/PrometheusFetcherProvider.java
index 1c3178d..ffd3c76 100644
--- a/oap-server/server-fetcher-plugin/prometheus-fetcher-plugin/src/main/java/org/apache/skywalking/oap/server/fetcher/prometheus/provider/PrometheusFetcherProvider.java
+++ b/oap-server/server-fetcher-plugin/prometheus-fetcher-plugin/src/main/java/org/apache/skywalking/oap/server/fetcher/prometheus/provider/PrometheusFetcherProvider.java
@@ -127,6 +127,9 @@ public class PrometheusFetcherProvider extends ModuleProvider {
                                 while ((mf = p.parse(now)) != null) {
                                     result.addAll(mf.getMetrics().stream()
                                         .peek(metric -> {
+                                            if (Objects.isNull(sc.getLabels())) {
+                                                return;
+                                            }
                                             Map<String, String> extraLabels = Maps.newHashMap(sc.getLabels());
                                             extraLabels.put("instance", url);
                                             extraLabels.forEach((key, value) -> {