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

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 76d003ec03 MAL Labeled metrics support additional attributes. (#13625)
76d003ec03 is described below

commit 76d003ec0369ca38efc3a5a4328627af000673a8
Author: Wan Kai <[email protected]>
AuthorDate: Wed Dec 17 22:03:01 2025 +0800

    MAL Labeled metrics support additional attributes. (#13625)
---
 docs/en/changes/changes.md                         |  1 +
 .../metrics-additional-attributes.md               |  1 -
 .../oap/meter/analyzer/dsl/SampleFamily.java       |  3 -
 .../meter/function/avg/AvgLabeledFunction.java     | 62 +++++++++++++++++++++
 .../function/latest/LatestLabeledFunction.java     | 62 +++++++++++++++++++++
 .../meter/function/max/MaxLabeledFunction.java     | 61 ++++++++++++++++++++
 .../meter/function/min/MinLabeledFunction.java     | 62 +++++++++++++++++++++
 .../meter/function/sum/SumLabeledFunction.java     | 62 +++++++++++++++++++++
 .../sumpermin/SumPerMinLabeledFunction.java        | 62 +++++++++++++++++++++
 .../meter/function/avg/AvgLabeledFunctionTest.java | 65 ++++++++++++++++++++--
 .../function/latest/LatestLabeledFunctionTest.java | 34 +++++++----
 .../meter/function/max/MaxLabeledFunctionTest.java | 34 +++++++----
 .../meter/function/min/MinLabeledFunctionTest.java | 34 +++++++----
 .../meter/function/sum/SumLabeledFunctionTest.java | 50 +++++++++--------
 .../sumpermin/SumPerMinLabeledFunctionTest.java    |  9 ++-
 15 files changed, 532 insertions(+), 70 deletions(-)

diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index 9eac35f638..ea1b50e003 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -12,6 +12,7 @@
 * Fail fast if SampleFamily is empty after MAL filter expression.
 * Fix range matrix and scalar binary operation in PromQL.
 * Add `LatestLabeledFunction` for meter.
+* MAL Labeled metrics support additional attributes.
 
 #### UI
 * Fix the missing icon in new native trace view.
diff --git a/docs/en/concepts-and-designs/metrics-additional-attributes.md 
b/docs/en/concepts-and-designs/metrics-additional-attributes.md
index 460d2e6c01..1d04f97a50 100644
--- a/docs/en/concepts-and-designs/metrics-additional-attributes.md
+++ b/docs/en/concepts-and-designs/metrics-additional-attributes.md
@@ -52,7 +52,6 @@ kubernetes_service_apdex = 
from(K8SService.protocol.http.latency).filter(detectP
 In the MAL script, you can use the [decorate](mal.md#decorate-function) 
function to decorate the source, and must follow the following rules:
 - The decorate function must after service() function.
 - Not supported for histogram metrics.
-- Not supported for labeled metrics.
 
 SkyWalking does not provide a default script for MAL, you can refer to the 
following example to set the `attr0` to the service `Layer`:
 ```text
diff --git 
a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java
 
b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java
index a51a968a7f..f72fed4cef 100644
--- 
a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java
+++ 
b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/SampleFamily.java
@@ -704,9 +704,6 @@ public class SampleFamily {
             if (ctx.isHistogram()) {
                 throw new IllegalStateException("decorate() not supported for 
histogram metrics");
             }
-            if (!ctx.getLabels().isEmpty()) {
-                throw new IllegalStateException("decorate() not supported for 
labeled metrics");
-            }
         });
         if (this == EMPTY) {
             return EMPTY;
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunction.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunction.java
index e86e71fc51..ced98ca675 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunction.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunction.java
@@ -18,6 +18,7 @@
 
 package org.apache.skywalking.oap.server.core.analysis.meter.function.avg;
 
+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.Meter;
@@ -40,6 +41,7 @@ import java.util.Set;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 
 @MeterFunction(functionName = "avgLabeled")
 @ToString
@@ -118,6 +120,13 @@ public abstract class AvgLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setServiceId(getServiceId());
         metrics.getSummation().copyFrom(getSummation());
         metrics.getCount().copyFrom(getCount());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -129,6 +138,13 @@ public abstract class AvgLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setServiceId(getServiceId());
         metrics.getSummation().copyFrom(getSummation());
         metrics.getCount().copyFrom(getCount());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -145,6 +161,30 @@ public abstract class AvgLabeledFunction extends Meter 
implements AcceptableValu
 
         this.entityId = remoteData.getDataStrings(0);
         this.serviceId = remoteData.getDataStrings(1);
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(2))) {
+            setAttr0(remoteData.getDataStrings(2));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(3))) {
+            setAttr1(remoteData.getDataStrings(3));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(4))) {
+            setAttr2(remoteData.getDataStrings(4));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(5))) {
+            setAttr3(remoteData.getDataStrings(5));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(6))) {
+            setAttr4(remoteData.getDataStrings(6));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(7))) {
+            setAttr5(remoteData.getDataStrings(7));
+        }
     }
 
     @Override
@@ -157,6 +197,13 @@ public abstract class AvgLabeledFunction extends Meter 
implements AcceptableValu
         remoteBuilder.addDataStrings(entityId);
         remoteBuilder.addDataStrings(serviceId);
 
+        remoteBuilder.addDataStrings(getAttr0() == null ? Const.EMPTY_STRING : 
getAttr0());
+        remoteBuilder.addDataStrings(getAttr1() == null ? Const.EMPTY_STRING : 
getAttr1());
+        remoteBuilder.addDataStrings(getAttr2() == null ? Const.EMPTY_STRING : 
getAttr2());
+        remoteBuilder.addDataStrings(getAttr3() == null ? Const.EMPTY_STRING : 
getAttr3());
+        remoteBuilder.addDataStrings(getAttr4() == null ? Const.EMPTY_STRING : 
getAttr4());
+        remoteBuilder.addDataStrings(getAttr5() == null ? Const.EMPTY_STRING : 
getAttr5());
+
         return remoteBuilder;
     }
 
@@ -169,6 +216,7 @@ public abstract class AvgLabeledFunction extends Meter 
implements AcceptableValu
 
     @Override
     public void accept(final MeterEntity entity, final DataTable value) {
+        decorate(entity);
         this.entityId = entity.id();
         this.serviceId = entity.serviceId();
         this.summation.append(value);
@@ -197,6 +245,13 @@ public abstract class AvgLabeledFunction extends Meter 
implements AcceptableValu
             metrics.setTimeBucket(((Number) 
converter.get(TIME_BUCKET)).longValue());
             metrics.setServiceId((String) 
converter.get(InstanceTraffic.SERVICE_ID));
             metrics.setEntityId((String) converter.get(ENTITY_ID));
+
+            metrics.setAttr0((String) converter.get(ATTR0));
+            metrics.setAttr1((String) converter.get(ATTR1));
+            metrics.setAttr2((String) converter.get(ATTR2));
+            metrics.setAttr3((String) converter.get(ATTR3));
+            metrics.setAttr4((String) converter.get(ATTR4));
+            metrics.setAttr5((String) converter.get(ATTR5));
             return metrics;
         }
 
@@ -208,6 +263,13 @@ public abstract class AvgLabeledFunction extends Meter 
implements AcceptableValu
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
             converter.accept(InstanceTraffic.SERVICE_ID, 
storageData.getServiceId());
             converter.accept(ENTITY_ID, storageData.getEntityId());
+
+            converter.accept(ATTR0, storageData.getAttr0());
+            converter.accept(ATTR1, storageData.getAttr1());
+            converter.accept(ATTR2, storageData.getAttr2());
+            converter.accept(ATTR3, storageData.getAttr3());
+            converter.accept(ATTR4, storageData.getAttr4());
+            converter.accept(ATTR5, storageData.getAttr5());
         }
     }
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunction.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunction.java
index 039d4d90a5..d7779da4b0 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunction.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunction.java
@@ -22,6 +22,7 @@ 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.Meter;
@@ -39,6 +40,7 @@ import 
org.apache.skywalking.oap.server.core.storage.annotation.ElasticSearch;
 import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
 import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
 import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 
 @MeterFunction(functionName = "latestLabeled")
 @ToString
@@ -69,6 +71,7 @@ public abstract class LatestLabeledFunction extends Meter 
implements AcceptableV
 
     @Override
     public void accept(final MeterEntity entity, final DataTable value) {
+        decorate(entity);
         setEntityId(entity.id());
         setServiceId(entity.serviceId());
         this.value = value;
@@ -93,6 +96,13 @@ public abstract class LatestLabeledFunction extends Meter 
implements AcceptableV
         metrics.setTimeBucket(toTimeBucketInHour());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -103,6 +113,13 @@ public abstract class LatestLabeledFunction extends Meter 
implements AcceptableV
         metrics.setTimeBucket(toTimeBucketInDay());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -120,6 +137,30 @@ public abstract class LatestLabeledFunction extends Meter 
implements AcceptableV
 
         setEntityId(remoteData.getDataStrings(0));
         setServiceId(remoteData.getDataStrings(1));
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(2))) {
+            setAttr0(remoteData.getDataStrings(2));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(3))) {
+            setAttr1(remoteData.getDataStrings(3));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(4))) {
+            setAttr2(remoteData.getDataStrings(4));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(5))) {
+            setAttr3(remoteData.getDataStrings(5));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(6))) {
+            setAttr4(remoteData.getDataStrings(6));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(7))) {
+            setAttr5(remoteData.getDataStrings(7));
+        }
     }
 
     @Override
@@ -131,6 +172,13 @@ public abstract class LatestLabeledFunction extends Meter 
implements AcceptableV
         remoteBuilder.addDataStrings(entityId);
         remoteBuilder.addDataStrings(serviceId);
 
+        remoteBuilder.addDataStrings(getAttr0() == null ? Const.EMPTY_STRING : 
getAttr0());
+        remoteBuilder.addDataStrings(getAttr1() == null ? Const.EMPTY_STRING : 
getAttr1());
+        remoteBuilder.addDataStrings(getAttr2() == null ? Const.EMPTY_STRING : 
getAttr2());
+        remoteBuilder.addDataStrings(getAttr3() == null ? Const.EMPTY_STRING : 
getAttr3());
+        remoteBuilder.addDataStrings(getAttr4() == null ? Const.EMPTY_STRING : 
getAttr4());
+        remoteBuilder.addDataStrings(getAttr5() == null ? Const.EMPTY_STRING : 
getAttr5());
+
         return remoteBuilder;
     }
 
@@ -157,6 +205,13 @@ public abstract class LatestLabeledFunction extends Meter 
implements AcceptableV
             metrics.setTimeBucket(((Number) 
converter.get(TIME_BUCKET)).longValue());
             metrics.setServiceId((String) 
converter.get(InstanceTraffic.SERVICE_ID));
             metrics.setEntityId((String) converter.get(ENTITY_ID));
+
+            metrics.setAttr0((String) converter.get(ATTR0));
+            metrics.setAttr1((String) converter.get(ATTR1));
+            metrics.setAttr2((String) converter.get(ATTR2));
+            metrics.setAttr3((String) converter.get(ATTR3));
+            metrics.setAttr4((String) converter.get(ATTR4));
+            metrics.setAttr5((String) converter.get(ATTR5));
             return metrics;
         }
 
@@ -166,6 +221,13 @@ public abstract class LatestLabeledFunction extends Meter 
implements AcceptableV
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
             converter.accept(InstanceTraffic.SERVICE_ID, 
storageData.getServiceId());
             converter.accept(ENTITY_ID, storageData.getEntityId());
+
+            converter.accept(ATTR0, storageData.getAttr0());
+            converter.accept(ATTR1, storageData.getAttr1());
+            converter.accept(ATTR2, storageData.getAttr2());
+            converter.accept(ATTR3, storageData.getAttr3());
+            converter.accept(ATTR4, storageData.getAttr4());
+            converter.accept(ATTR5, storageData.getAttr5());
         }
     }
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunction.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunction.java
index dff6d7a10a..a597e56d9e 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunction.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunction.java
@@ -21,6 +21,7 @@ package 
org.apache.skywalking.oap.server.core.analysis.meter.function.max;
 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.Meter;
@@ -40,6 +41,7 @@ import 
org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
 import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
 
 import java.util.Objects;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 
 @MeterFunction(functionName = "maxLabeled")
 @ToString
@@ -70,6 +72,7 @@ public abstract class MaxLabeledFunction extends Meter 
implements AcceptableValu
 
     @Override
     public void accept(final MeterEntity entity, final DataTable value) {
+        decorate(entity);
         setEntityId(entity.id());
         setServiceId(entity.serviceId());
         this.value.setMaxValue(value);
@@ -94,6 +97,13 @@ public abstract class MaxLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setTimeBucket(toTimeBucketInHour());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -104,6 +114,13 @@ public abstract class MaxLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setTimeBucket(toTimeBucketInDay());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -121,6 +138,30 @@ public abstract class MaxLabeledFunction extends Meter 
implements AcceptableValu
 
         setEntityId(remoteData.getDataStrings(0));
         setServiceId(remoteData.getDataStrings(1));
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(2))) {
+            setAttr0(remoteData.getDataStrings(2));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(3))) {
+            setAttr1(remoteData.getDataStrings(3));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(4))) {
+            setAttr2(remoteData.getDataStrings(4));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(5))) {
+            setAttr3(remoteData.getDataStrings(5));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(6))) {
+            setAttr4(remoteData.getDataStrings(6));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(7))) {
+            setAttr5(remoteData.getDataStrings(7));
+        }
     }
 
     @Override
@@ -132,6 +173,12 @@ public abstract class MaxLabeledFunction extends Meter 
implements AcceptableValu
         remoteBuilder.addDataStrings(entityId);
         remoteBuilder.addDataStrings(serviceId);
 
+        remoteBuilder.addDataStrings(getAttr0() == null ? Const.EMPTY_STRING : 
getAttr0());
+        remoteBuilder.addDataStrings(getAttr1() == null ? Const.EMPTY_STRING : 
getAttr1());
+        remoteBuilder.addDataStrings(getAttr2() == null ? Const.EMPTY_STRING : 
getAttr2());
+        remoteBuilder.addDataStrings(getAttr3() == null ? Const.EMPTY_STRING : 
getAttr3());
+        remoteBuilder.addDataStrings(getAttr4() == null ? Const.EMPTY_STRING : 
getAttr4());
+        remoteBuilder.addDataStrings(getAttr5() == null ? Const.EMPTY_STRING : 
getAttr5());
         return remoteBuilder;
     }
 
@@ -158,6 +205,13 @@ public abstract class MaxLabeledFunction extends Meter 
implements AcceptableValu
             metrics.setTimeBucket(((Number) 
converter.get(TIME_BUCKET)).longValue());
             metrics.setServiceId((String) 
converter.get(InstanceTraffic.SERVICE_ID));
             metrics.setEntityId((String) converter.get(ENTITY_ID));
+
+            metrics.setAttr0((String) converter.get(ATTR0));
+            metrics.setAttr1((String) converter.get(ATTR1));
+            metrics.setAttr2((String) converter.get(ATTR2));
+            metrics.setAttr3((String) converter.get(ATTR3));
+            metrics.setAttr4((String) converter.get(ATTR4));
+            metrics.setAttr5((String) converter.get(ATTR5));
             return metrics;
         }
 
@@ -167,6 +221,13 @@ public abstract class MaxLabeledFunction extends Meter 
implements AcceptableValu
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
             converter.accept(InstanceTraffic.SERVICE_ID, 
storageData.getServiceId());
             converter.accept(ENTITY_ID, storageData.getEntityId());
+
+            converter.accept(ATTR0, storageData.getAttr0());
+            converter.accept(ATTR1, storageData.getAttr1());
+            converter.accept(ATTR2, storageData.getAttr2());
+            converter.accept(ATTR3, storageData.getAttr3());
+            converter.accept(ATTR4, storageData.getAttr4());
+            converter.accept(ATTR5, storageData.getAttr5());
         }
     }
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunction.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunction.java
index 82d74a9501..da1fc3966f 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunction.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunction.java
@@ -21,6 +21,7 @@ package 
org.apache.skywalking.oap.server.core.analysis.meter.function.min;
 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.Meter;
@@ -40,6 +41,7 @@ import 
org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
 import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
 
 import java.util.Objects;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 
 @MeterFunction(functionName = "minLabeled")
 @ToString
@@ -70,6 +72,7 @@ public abstract class MinLabeledFunction extends Meter 
implements AcceptableValu
 
     @Override
     public void accept(final MeterEntity entity, final DataTable value) {
+        decorate(entity);
         setEntityId(entity.id());
         setServiceId(entity.serviceId());
         this.value.setMinValue(value);
@@ -94,6 +97,13 @@ public abstract class MinLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setTimeBucket(toTimeBucketInHour());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -104,6 +114,13 @@ public abstract class MinLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setTimeBucket(toTimeBucketInDay());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -121,6 +138,30 @@ public abstract class MinLabeledFunction extends Meter 
implements AcceptableValu
 
         setEntityId(remoteData.getDataStrings(0));
         setServiceId(remoteData.getDataStrings(1));
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(2))) {
+            setAttr0(remoteData.getDataStrings(2));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(3))) {
+            setAttr1(remoteData.getDataStrings(3));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(4))) {
+            setAttr2(remoteData.getDataStrings(4));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(5))) {
+            setAttr3(remoteData.getDataStrings(5));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(6))) {
+            setAttr4(remoteData.getDataStrings(6));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(7))) {
+            setAttr5(remoteData.getDataStrings(7));
+        }
     }
 
     @Override
@@ -132,6 +173,13 @@ public abstract class MinLabeledFunction extends Meter 
implements AcceptableValu
         remoteBuilder.addDataStrings(entityId);
         remoteBuilder.addDataStrings(serviceId);
 
+        remoteBuilder.addDataStrings(getAttr0() == null ? Const.EMPTY_STRING : 
getAttr0());
+        remoteBuilder.addDataStrings(getAttr1() == null ? Const.EMPTY_STRING : 
getAttr1());
+        remoteBuilder.addDataStrings(getAttr2() == null ? Const.EMPTY_STRING : 
getAttr2());
+        remoteBuilder.addDataStrings(getAttr3() == null ? Const.EMPTY_STRING : 
getAttr3());
+        remoteBuilder.addDataStrings(getAttr4() == null ? Const.EMPTY_STRING : 
getAttr4());
+        remoteBuilder.addDataStrings(getAttr5() == null ? Const.EMPTY_STRING : 
getAttr5());
+
         return remoteBuilder;
     }
 
@@ -158,6 +206,13 @@ public abstract class MinLabeledFunction extends Meter 
implements AcceptableValu
             metrics.setTimeBucket(((Number) 
converter.get(TIME_BUCKET)).longValue());
             metrics.setServiceId((String) 
converter.get(InstanceTraffic.SERVICE_ID));
             metrics.setEntityId((String) converter.get(ENTITY_ID));
+
+            metrics.setAttr0((String) converter.get(ATTR0));
+            metrics.setAttr1((String) converter.get(ATTR1));
+            metrics.setAttr2((String) converter.get(ATTR2));
+            metrics.setAttr3((String) converter.get(ATTR3));
+            metrics.setAttr4((String) converter.get(ATTR4));
+            metrics.setAttr5((String) converter.get(ATTR5));
             return metrics;
         }
 
@@ -167,6 +222,13 @@ public abstract class MinLabeledFunction extends Meter 
implements AcceptableValu
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
             converter.accept(InstanceTraffic.SERVICE_ID, 
storageData.getServiceId());
             converter.accept(ENTITY_ID, storageData.getEntityId());
+
+            converter.accept(ATTR0, storageData.getAttr0());
+            converter.accept(ATTR1, storageData.getAttr1());
+            converter.accept(ATTR2, storageData.getAttr2());
+            converter.accept(ATTR3, storageData.getAttr3());
+            converter.accept(ATTR4, storageData.getAttr4());
+            converter.accept(ATTR5, storageData.getAttr5());
         }
     }
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunction.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunction.java
index b999d9f128..4c6ecb4f60 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunction.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunction.java
@@ -22,6 +22,7 @@ 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.Meter;
@@ -39,6 +40,7 @@ import 
org.apache.skywalking.oap.server.core.storage.annotation.ElasticSearch;
 import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
 import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
 import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 
 @MeterFunction(functionName = "sumLabeled")
 @ToString
@@ -83,6 +85,13 @@ public abstract class SumLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setTimeBucket(toTimeBucketInHour());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -93,6 +102,13 @@ public abstract class SumLabeledFunction extends Meter 
implements AcceptableValu
         metrics.setTimeBucket(toTimeBucketInDay());
         metrics.setServiceId(getServiceId());
         metrics.getValue().copyFrom(getValue());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -108,6 +124,30 @@ public abstract class SumLabeledFunction extends Meter 
implements AcceptableValu
 
         this.entityId = remoteData.getDataStrings(0);
         this.serviceId = remoteData.getDataStrings(1);
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(2))) {
+            setAttr0(remoteData.getDataStrings(2));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(3))) {
+            setAttr1(remoteData.getDataStrings(3));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(4))) {
+            setAttr2(remoteData.getDataStrings(4));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(5))) {
+            setAttr3(remoteData.getDataStrings(5));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(6))) {
+            setAttr4(remoteData.getDataStrings(6));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(7))) {
+            setAttr5(remoteData.getDataStrings(7));
+        }
     }
 
     @Override
@@ -119,6 +159,13 @@ public abstract class SumLabeledFunction extends Meter 
implements AcceptableValu
         remoteBuilder.addDataStrings(entityId);
         remoteBuilder.addDataStrings(serviceId);
 
+        remoteBuilder.addDataStrings(getAttr0() == null ? Const.EMPTY_STRING : 
getAttr0());
+        remoteBuilder.addDataStrings(getAttr1() == null ? Const.EMPTY_STRING : 
getAttr1());
+        remoteBuilder.addDataStrings(getAttr2() == null ? Const.EMPTY_STRING : 
getAttr2());
+        remoteBuilder.addDataStrings(getAttr3() == null ? Const.EMPTY_STRING : 
getAttr3());
+        remoteBuilder.addDataStrings(getAttr4() == null ? Const.EMPTY_STRING : 
getAttr4());
+        remoteBuilder.addDataStrings(getAttr5() == null ? Const.EMPTY_STRING : 
getAttr5());
+
         return remoteBuilder;
     }
 
@@ -131,6 +178,7 @@ public abstract class SumLabeledFunction extends Meter 
implements AcceptableValu
 
     @Override
     public void accept(final MeterEntity entity, final DataTable value) {
+        decorate(entity);
         this.entityId = entity.id();
         this.serviceId = entity.serviceId();
         this.value.append(value);
@@ -154,6 +202,13 @@ public abstract class SumLabeledFunction extends Meter 
implements AcceptableValu
             metrics.setTimeBucket(((Number) 
converter.get(TIME_BUCKET)).longValue());
             metrics.setServiceId((String) 
converter.get(InstanceTraffic.SERVICE_ID));
             metrics.setEntityId((String) converter.get(ENTITY_ID));
+
+            metrics.setAttr0((String) converter.get(ATTR0));
+            metrics.setAttr1((String) converter.get(ATTR1));
+            metrics.setAttr2((String) converter.get(ATTR2));
+            metrics.setAttr3((String) converter.get(ATTR3));
+            metrics.setAttr4((String) converter.get(ATTR4));
+            metrics.setAttr5((String) converter.get(ATTR5));
             return metrics;
         }
 
@@ -163,6 +218,13 @@ public abstract class SumLabeledFunction extends Meter 
implements AcceptableValu
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
             converter.accept(InstanceTraffic.SERVICE_ID, 
storageData.getServiceId());
             converter.accept(ENTITY_ID, storageData.getEntityId());
+
+            converter.accept(ATTR0, storageData.getAttr0());
+            converter.accept(ATTR1, storageData.getAttr1());
+            converter.accept(ATTR2, storageData.getAttr2());
+            converter.accept(ATTR3, storageData.getAttr3());
+            converter.accept(ATTR4, storageData.getAttr4());
+            converter.accept(ATTR5, storageData.getAttr5());
         }
     }
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunction.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunction.java
index 21c548e2a5..dd1ab0153c 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunction.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunction.java
@@ -21,6 +21,7 @@ package 
org.apache.skywalking.oap.server.core.analysis.meter.function.sumpermin;
 import java.util.Objects;
 import lombok.Getter;
 import lombok.Setter;
+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.Meter;
@@ -38,6 +39,7 @@ import 
org.apache.skywalking.oap.server.core.storage.annotation.ElasticSearch;
 import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
 import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
 import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
 
 @MeterFunction(functionName = "sumPerMinLabeled")
 public abstract class SumPerMinLabeledFunction extends Meter implements 
AcceptableValue<DataTable>, LabeledValueHolder {
@@ -71,6 +73,7 @@ public abstract class SumPerMinLabeledFunction extends Meter 
implements Acceptab
 
     @Override
     public void accept(MeterEntity entity, DataTable value) {
+        decorate(entity);
         setEntityId(entity.id());
         setServiceId(entity.serviceId());
         this.total.append(value);
@@ -106,6 +109,13 @@ public abstract class SumPerMinLabeledFunction extends 
Meter implements Acceptab
         metrics.setTimeBucket(toTimeBucketInHour());
         metrics.setServiceId(getServiceId());
         metrics.getTotal().copyFrom(getTotal());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -116,6 +126,13 @@ public abstract class SumPerMinLabeledFunction extends 
Meter implements Acceptab
         metrics.setTimeBucket(toTimeBucketInDay());
         metrics.setServiceId(getServiceId());
         metrics.getTotal().copyFrom(getTotal());
+
+        metrics.setAttr0(getAttr0());
+        metrics.setAttr1(getAttr1());
+        metrics.setAttr2(getAttr2());
+        metrics.setAttr3(getAttr3());
+        metrics.setAttr4(getAttr4());
+        metrics.setAttr5(getAttr5());
         return metrics;
     }
 
@@ -133,6 +150,30 @@ public abstract class SumPerMinLabeledFunction extends 
Meter implements Acceptab
 
         setEntityId(remoteData.getDataStrings(0));
         setServiceId(remoteData.getDataStrings(1));
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(2))) {
+            setAttr0(remoteData.getDataStrings(2));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(3))) {
+            setAttr1(remoteData.getDataStrings(3));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(4))) {
+            setAttr2(remoteData.getDataStrings(4));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(5))) {
+            setAttr3(remoteData.getDataStrings(5));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(6))) {
+            setAttr4(remoteData.getDataStrings(6));
+        }
+
+        if (StringUtil.isNotEmpty(remoteData.getDataStrings(7))) {
+            setAttr5(remoteData.getDataStrings(7));
+        }
     }
 
     @Override
@@ -144,6 +185,13 @@ public abstract class SumPerMinLabeledFunction extends 
Meter implements Acceptab
 
         remoteBuilder.addDataStrings(getEntityId());
         remoteBuilder.addDataStrings(getServiceId());
+
+        remoteBuilder.addDataStrings(getAttr0() == null ? Const.EMPTY_STRING : 
getAttr0());
+        remoteBuilder.addDataStrings(getAttr1() == null ? Const.EMPTY_STRING : 
getAttr1());
+        remoteBuilder.addDataStrings(getAttr2() == null ? Const.EMPTY_STRING : 
getAttr2());
+        remoteBuilder.addDataStrings(getAttr3() == null ? Const.EMPTY_STRING : 
getAttr3());
+        remoteBuilder.addDataStrings(getAttr4() == null ? Const.EMPTY_STRING : 
getAttr4());
+        remoteBuilder.addDataStrings(getAttr5() == null ? Const.EMPTY_STRING : 
getAttr5());
         return remoteBuilder;
     }
 
@@ -167,6 +215,13 @@ public abstract class SumPerMinLabeledFunction extends 
Meter implements Acceptab
             metrics.setTimeBucket(((Number) 
converter.get(TIME_BUCKET)).longValue());
             metrics.setServiceId((String) 
converter.get(InstanceTraffic.SERVICE_ID));
             metrics.setEntityId((String) converter.get(ENTITY_ID));
+
+            metrics.setAttr0((String) converter.get(ATTR0));
+            metrics.setAttr1((String) converter.get(ATTR1));
+            metrics.setAttr2((String) converter.get(ATTR2));
+            metrics.setAttr3((String) converter.get(ATTR3));
+            metrics.setAttr4((String) converter.get(ATTR4));
+            metrics.setAttr5((String) converter.get(ATTR5));
             return metrics;
         }
 
@@ -177,6 +232,13 @@ public abstract class SumPerMinLabeledFunction extends 
Meter implements Acceptab
             converter.accept(TIME_BUCKET, storageData.getTimeBucket());
             converter.accept(InstanceTraffic.SERVICE_ID, 
storageData.getServiceId());
             converter.accept(ENTITY_ID, storageData.getEntityId());
+
+            converter.accept(ATTR0, storageData.getAttr0());
+            converter.accept(ATTR1, storageData.getAttr1());
+            converter.accept(ATTR2, storageData.getAttr2());
+            converter.accept(ATTR3, storageData.getAttr3());
+            converter.accept(ATTR4, storageData.getAttr4());
+            converter.accept(ATTR5, storageData.getAttr5());
         }
     }
 
diff --git 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunctionTest.java
 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunctionTest.java
index df94f118c9..54a549a0d6 100644
--- 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunctionTest.java
+++ 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgLabeledFunctionTest.java
@@ -20,7 +20,9 @@ package 
org.apache.skywalking.oap.server.core.analysis.meter.function.avg;
 
 import io.vavr.collection.Stream;
 import org.apache.skywalking.oap.server.core.analysis.Layer;
+import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity;
+import 
org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
 import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.config.NamingControl;
 import org.apache.skywalking.oap.server.core.config.group.EndpointNameGrouping;
@@ -28,6 +30,7 @@ import 
org.apache.skywalking.oap.server.core.storage.type.HashMapConverter;
 import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mockito;
@@ -55,6 +58,12 @@ public class AvgLabeledFunctionTest {
             new NamingControl(512, 512, 512, new EndpointNameGrouping()));
     }
 
+    @BeforeEach
+    public void before() {
+        function = new AvgLabeledFunctionInst();
+        
function.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+    }
+
     @AfterAll
     public static void tearDown() {
         MeterEntity.setNamingControl(null);
@@ -84,18 +93,22 @@ public class AvgLabeledFunctionTest {
 
     @Test
     public void testSerialize() {
-        function.accept(
-            MeterEntity.newService("request_count", Layer.GENERAL), 
build(asList("200", "404"), asList(10L, 2L)));
+        MeterEntity meterEntity = MeterEntity.newService("request_count", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, build(asList("200", "404"), asList(10L, 
2L)));
         AvgLabeledFunction function2 = Mockito.spy(AvgLabeledFunction.class);
         function2.deserialize(function.serialize().build());
         assertThat(function2.getEntityId()).isEqualTo(function.getEntityId());
         
assertThat(function2.getTimeBucket()).isEqualTo(function.getTimeBucket());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
+
     }
 
     @Test
     public void testBuilder() throws IllegalAccessException, 
InstantiationException {
-        function.accept(
-            MeterEntity.newService("request_count", Layer.GENERAL), 
build(asList("200", "404"), asList(10L, 2L)));
+        MeterEntity meterEntity = MeterEntity.newService("request_count", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, build(asList("200", "404"), asList(10L, 
2L)));
         function.calculate();
         StorageBuilder<AvgLabeledFunction> storageBuilder = 
function.builder().newInstance();
 
@@ -108,6 +121,43 @@ public class AvgLabeledFunctionTest {
 
         AvgLabeledFunction function2 = storageBuilder.storage2Entity(new 
HashMapConverter.ToEntity(map));
         assertThat(function2.getValue()).isEqualTo(function.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
+    }
+
+    @Test
+    public void testToHour() {
+        MeterEntity meterEntity1 = MeterEntity.newService("request_count", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, build(asList("200", "404"), asList(10L, 
2L)));
+        MeterEntity meterEntity2 = MeterEntity.newService("request_count", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, build(asList("200", "500"), asList(2L, 
3L)));
+        function.calculate();
+
+        final AvgLabeledFunction hourFunction = (AvgLabeledFunction) 
function.toHour();
+        hourFunction.calculate();
+
+        
assertThat(function.getValue().sortedKeys(Comparator.naturalOrder())).isEqualTo(asList("200",
 "404", "500"));
+        
assertThat(function.getValue().sortedValues(Comparator.naturalOrder())).isEqualTo(asList(6L,
 2L, 3L));
+        assertThat(hourFunction.getAttr0()).isEqualTo("testAttr");
+    }
+
+    @Test
+    public void testToDay() {
+        MeterEntity meterEntity1 = MeterEntity.newService("request_count", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, build(asList("200", "404"), asList(10L, 
2L)));
+        MeterEntity meterEntity2 = MeterEntity.newService("request_count", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, build(asList("200", "500"), asList(2L, 
3L)));
+        function.calculate();
+
+        final AvgLabeledFunction dayFunction = (AvgLabeledFunction) 
function.toDay();
+        dayFunction.calculate();
+
+        
assertThat(function.getValue().sortedKeys(Comparator.naturalOrder())).isEqualTo(asList("200",
 "404", "500"));
+        
assertThat(function.getValue().sortedValues(Comparator.naturalOrder())).isEqualTo(asList(6L,
 2L, 3L));
+        assertThat(dayFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     private DataTable build(List<String> keys, List<Long> values) {
@@ -134,4 +184,11 @@ public class AvgLabeledFunctionTest {
         List<Long> values = 
function.getSummation().sortedValues(Comparator.comparingLong(Long::parseLong));
         assertThat(values).isEqualTo(expectedValues);
     }
+
+    private static class AvgLabeledFunctionInst extends AvgLabeledFunction {
+        @Override
+        public AcceptableValue<DataTable> createNew() {
+            return new AvgLabeledFunctionTest.AvgLabeledFunctionInst();
+        }
+    }
 }
diff --git 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunctionTest.java
 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunctionTest.java
index 7492868930..d722986d5d 100644
--- 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunctionTest.java
+++ 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/latest/LatestLabeledFunctionTest.java
@@ -87,37 +87,43 @@ public class LatestLabeledFunctionTest {
 
     @Test
     public void testToHour() {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_2);
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final LatestLabeledFunction hourFunction = (LatestLabeledFunction) 
function.toHour();
         hourFunction.calculate();
 
         assertThat(hourFunction.getValue()).isEqualTo(HTTP_CODE_COUNT_2);
+        assertThat(hourFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testToDay() {
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_1
-        );
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_2
-        );
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final LatestLabeledFunction dayFunction = (LatestLabeledFunction) 
function.toDay();
         dayFunction.calculate();
 
         assertThat(dayFunction.getValue()).isEqualTo(HTTP_CODE_COUNT_2);
+        assertThat(dayFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testSerialize() {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, HTTP_CODE_COUNT_1);
 
         LatestLabeledFunction function2 = new LatestLabeledFunctionInst();
         function2.deserialize(function.serialize().build());
@@ -126,11 +132,14 @@ public class LatestLabeledFunctionTest {
         
assertThat(function2.getTimeBucket()).isEqualTo(function.getTimeBucket());
         
assertThat(function2.getServiceId()).isEqualTo(function.getServiceId());
         assertThat(function2.getValue()).isEqualTo(function.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     @Test
     public void testBuilder() throws IllegalAccessException, 
InstantiationException {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, HTTP_CODE_COUNT_1);
         function.calculate();
 
         StorageBuilder<LatestLabeledFunction> storageBuilder = 
function.builder().newInstance();
@@ -143,6 +152,7 @@ public class LatestLabeledFunctionTest {
         LatestLabeledFunction function2 = storageBuilder.storage2Entity(new 
HashMapConverter.ToEntity(map));
 
         assertThat(function2.getValue()).isEqualTo(function.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     private static class LatestLabeledFunctionInst extends 
LatestLabeledFunction {
diff --git 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunctionTest.java
 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunctionTest.java
index 012013688e..44a13ddc79 100644
--- 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunctionTest.java
+++ 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/max/MaxLabeledFunctionTest.java
@@ -86,37 +86,43 @@ public class MaxLabeledFunctionTest {
 
     @Test
     public void testToHour() {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_2);
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final MaxLabeledFunction hourFunction = (MaxLabeledFunction) 
function.toHour();
         hourFunction.calculate();
 
         assertThat(hourFunction.getValue()).isEqualTo(HTTP_CODE_COUNT_3);
+        assertThat(hourFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testToDay() {
-        function.accept(
-                MeterEntity.newService("service-test", Layer.GENERAL),
-                HTTP_CODE_COUNT_1
-        );
-        function.accept(
-                MeterEntity.newService("service-test", Layer.GENERAL),
-                HTTP_CODE_COUNT_2
-        );
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final MaxLabeledFunction dayFunction = (MaxLabeledFunction) 
function.toDay();
         dayFunction.calculate();
 
         assertThat(dayFunction.getValue()).isEqualTo(HTTP_CODE_COUNT_3);
+        assertThat(dayFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testSerialize() {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, HTTP_CODE_COUNT_1);
 
         MaxLabeledFunction function2 = new MaxLabeledFunctionInst();
         function2.deserialize(function.serialize().build());
@@ -125,11 +131,14 @@ public class MaxLabeledFunctionTest {
         
assertThat(function2.getTimeBucket()).isEqualTo(function.getTimeBucket());
         
assertThat(function2.getServiceId()).isEqualTo(function.getServiceId());
         assertThat(function2.getValue()).isEqualTo(function.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     @Test
     public void testBuilder() throws IllegalAccessException, 
InstantiationException {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, HTTP_CODE_COUNT_1);
         function.calculate();
 
         StorageBuilder<MaxLabeledFunction> storageBuilder = 
function.builder().newInstance();
@@ -142,6 +151,7 @@ public class MaxLabeledFunctionTest {
         MaxLabeledFunction function2 = storageBuilder.storage2Entity(new 
HashMapConverter.ToEntity(map));
 
         assertThat(function2.getValue()).isEqualTo(function.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     private static class MaxLabeledFunctionInst extends MaxLabeledFunction {
diff --git 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunctionTest.java
 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunctionTest.java
index 7005529f21..a6d3b494aa 100644
--- 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunctionTest.java
+++ 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/min/MinLabeledFunctionTest.java
@@ -86,37 +86,43 @@ public class MinLabeledFunctionTest {
 
     @Test
     public void testToHour() {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_2);
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final MinLabeledFunction hourFunction = (MinLabeledFunction) 
function.toHour();
         hourFunction.calculate();
 
         assertThat(hourFunction.getValue()).isEqualTo(HTTP_CODE_COUNT_3);
+        assertThat(hourFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testToDay() {
-        function.accept(
-                MeterEntity.newService("service-test", Layer.GENERAL),
-                HTTP_CODE_COUNT_1
-        );
-        function.accept(
-                MeterEntity.newService("service-test", Layer.GENERAL),
-                HTTP_CODE_COUNT_2
-        );
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final MinLabeledFunction dayFunction = (MinLabeledFunction) 
function.toDay();
         dayFunction.calculate();
 
         assertThat(dayFunction.getValue()).isEqualTo(HTTP_CODE_COUNT_3);
+        assertThat(dayFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testSerialize() {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, HTTP_CODE_COUNT_1);
 
         MinLabeledFunction function2 = new MinLabeledFunctionInst();
         function2.deserialize(function.serialize().build());
@@ -125,11 +131,14 @@ public class MinLabeledFunctionTest {
         
assertThat(function2.getTimeBucket()).isEqualTo(function.getTimeBucket());
         
assertThat(function2.getServiceId()).isEqualTo(function.getServiceId());
         assertThat(function2.getValue()).isEqualTo(function.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     @Test
     public void testBuilder() throws IllegalAccessException, 
InstantiationException {
-        function.accept(MeterEntity.newService("service-test", Layer.GENERAL), 
HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, HTTP_CODE_COUNT_1);
         function.calculate();
 
         StorageBuilder<MinLabeledFunction> storageBuilder = 
function.builder().newInstance();
@@ -142,6 +151,7 @@ public class MinLabeledFunctionTest {
         MinLabeledFunction function2 = storageBuilder.storage2Entity(new 
HashMapConverter.ToEntity(map));
 
         assertThat(function2.getValue()).isEqualTo(function.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     private static class MinLabeledFunctionInst extends MinLabeledFunction {
diff --git 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunctionTest.java
 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunctionTest.java
index ad83b0dcd2..34455a7ca1 100644
--- 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunctionTest.java
+++ 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumLabeledFunctionTest.java
@@ -37,6 +37,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import static 
org.apache.skywalking.oap.server.core.analysis.meter.function.sum.SumLabeledFunction.VALUE;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 
 @ExtendWith(MockitoExtension.class)
 public class SumLabeledFunctionTest {
@@ -79,60 +80,60 @@ public class SumLabeledFunctionTest {
 
     @Test
     public void testToHour() {
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_1
-        );
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_2
-        );
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final SumLabeledFunction hourFunction = (SumLabeledFunction) 
function.toHour();
         hourFunction.calculate();
 
         Assertions.assertEquals(hourFunction.getValue(), new 
DataTable("200,3|301,2|404,7|502,9|505,1"));
+        assertThat(hourFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testToDay() {
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_1
-        );
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_2
-        );
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
         function.calculate();
 
         final SumLabeledFunction dayFunction = (SumLabeledFunction) 
function.toDay();
         dayFunction.calculate();
 
         Assertions.assertEquals(dayFunction.getValue(), new 
DataTable("200,3|301,2|404,7|502,9|505,1"));
+        assertThat(dayFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test
     public void testSerialization() {
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_1
-        );
+        MeterEntity meterEntity1 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
+        function.accept(meterEntity1, HTTP_CODE_COUNT_1);
+        MeterEntity meterEntity2 = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, HTTP_CODE_COUNT_2);
 
         SumLabeledFunction function2 = new SumLabeledFunctionInst();
         function2.deserialize(function.serialize().build());
 
         Assertions.assertEquals(function, function2);
         Assertions.assertEquals(function.getValue(), function2.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     @Test
     public void testBuilder() throws IllegalAccessException, 
InstantiationException {
-        function.accept(
-            MeterEntity.newService("service-test", Layer.GENERAL),
-            HTTP_CODE_COUNT_1
-        );
+        MeterEntity meterEntity = MeterEntity.newService("service-test", 
Layer.GENERAL);
+        meterEntity.setAttr0("testAttr");
+        function.accept(meterEntity, HTTP_CODE_COUNT_1);
         function.calculate();
 
         StorageBuilder<SumLabeledFunction> storageBuilder = 
function.builder().newInstance();
@@ -146,6 +147,7 @@ public class SumLabeledFunctionTest {
 
         Assertions.assertEquals(function, function2);
         Assertions.assertEquals(function2.getValue(), function2.getValue());
+        assertThat(function2.getAttr0()).isEqualTo(function.getAttr0());
     }
 
     private static class SumLabeledFunctionInst extends SumLabeledFunction {
diff --git 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunctionTest.java
 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunctionTest.java
index 125700b88f..bf2ad0dd0e 100644
--- 
a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunctionTest.java
+++ 
b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinLabeledFunctionTest.java
@@ -92,9 +92,13 @@ public class SumPerMinLabeledFunctionTest {
 
     @Test
     public void testHour() {
+        MeterEntity meterEntity1 = MeterEntity.newService("sum_sync_time", 
Layer.GENERAL);
+        meterEntity1.setAttr0("testAttr");
         
function.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
-        function.accept(MeterEntity.newService("sum_sync_time", 
Layer.GENERAL), table1);
-        function.accept(MeterEntity.newService("sum_sync_time", 
Layer.GENERAL), table2);
+        function.accept(meterEntity1, table1);
+        MeterEntity meterEntity2 = MeterEntity.newService("sum_sync_time", 
Layer.GENERAL);
+        meterEntity2.setAttr0("testAttr");
+        function.accept(meterEntity2, table2);
         function.calculate();
         final SumPerMinLabeledFunction hourFunction = 
(SumPerMinLabeledFunction) function.toHour();
         hourFunction.calculate();
@@ -105,6 +109,7 @@ public class SumPerMinLabeledFunctionTest {
             result.put(key, result.get(key) / 60);
         }
         assertThat(hourFunction.getValue()).isEqualTo(result);
+        assertThat(hourFunction.getAttr0()).isEqualTo("testAttr");
     }
 
     @Test

Reply via email to