pg-yang commented on code in PR #9622:
URL: https://github.com/apache/skywalking/pull/9622#discussion_r973198816


##########
docs/menu.yml:
##########
@@ -111,6 +111,8 @@ catalog:
                 path: "/en/setup/backend/trace-sampling"
               - name: "Detect Slow Database Statement"
                 path: "/en/setup/backend/slow-db-statement"
+              - name: "Detect Slow Database Statement"

Review Comment:
   Will be done



##########
oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/vservice/VirtualCacheProcessor.java:
##########
@@ -0,0 +1,158 @@
+/*
+ * 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.analyzer.provider.trace.parser.listener.vservice;
+
+import com.google.gson.Gson;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanLayer;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
+import org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleConfig;
+import 
org.apache.skywalking.oap.server.analyzer.provider.trace.parser.SpanTags;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
+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.config.NamingControl;
+import org.apache.skywalking.oap.server.core.source.ServiceMeta;
+import org.apache.skywalking.oap.server.core.source.Source;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowWrite;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheWrite;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RequiredArgsConstructor
+public class VirtualCacheProcessor implements VirtualServiceProcessor {
+
+    private final NamingControl namingControl;
+
+    private final AnalyzerModuleConfig config;
+
+    private final List<Source> sourceList = new ArrayList<>();
+
+    @Override
+    public void prepareVSIfNecessary(SpanObject span, SegmentObject 
segmentObject) {
+        if (span.getSpanLayer() != SpanLayer.Cache) {
+            return;
+        }
+        Map<String, String> tags = span.getTagsList().stream()
+                .collect(Collectors.toMap(KeyStringValuePair::getKey, 
KeyStringValuePair::getValue));
+        if (!(tags.containsKey(SpanTags.CACHE_KEY) && 
tags.containsKey(SpanTags.CACHE_OP) && tags.containsKey(SpanTags.CACHE_CMD) && 
tags.containsKey(SpanTags.CACHE_TYPE))) {
+            return;
+        }
+        String cacheType = tags.get(SpanTags.CACHE_TYPE).toLowerCase();
+        String peer = span.getPeer();
+        // peer is blank if it's a local span
+        if (StringUtil.isBlank(peer)) {
+            peer = tags.get(SpanTags.CACHE_TYPE) + "-local";
+        }
+        long timeBucket = TimeBucket.getMinuteTimeBucket(span.getStartTime());
+        String serviceName = namingControl.formatServiceName(peer);
+        int latency = (int) (span.getEndTime() - span.getStartTime());
+        if (latency > 0) {
+            log.info("latency data : {}", new Gson().toJson(span));
+        }
+        sourceList.add(parseServiceMeta(serviceName, timeBucket));
+        String op = tags.get(SpanTags.CACHE_OP);
+        if ("write".equals(op)) {
+            sourceList.add(parseWriteMetrics(span, latency, serviceName, 
timeBucket));
+            if (latency > 
config.getCacheWriteLatencyThresholdsAndWatcher().getThreshold(cacheType)) {
+                sourceList.add(parseSlowWrite(segmentObject, latency, 
serviceName, span, tags));
+            }
+        } else if ("read".equals(op)) {
+            sourceList.add(parseReadMetrics(span, latency, serviceName, 
timeBucket));
+            if (latency > 
config.getCacheReadLatencyThresholdsAndWatcher().getThreshold(cacheType)) {
+                sourceList.add(parseSlowRead(segmentObject, latency, 
serviceName, span, tags));
+            }
+        } else {
+            log.warn("Illegal tag value :{} for 'cache.op' , only write/read 
would be accepted", op);

Review Comment:
   I log this warning message  when  client send a span which contains op tag , 
but the value isn't read/write . 
   After all , we only analyze read/write operation , And could not guarantee 
every plugin is correct , I  think .



##########
test/e2e-v2/cases/storage/storage-cases.yaml:
##########
@@ -47,7 +47,7 @@ cases:
   - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls
     expected: expected/traces-list.yml
   # negative tags search: relationship should be logical AND instead of 
logical OR
-  - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls --tags 
http.method=POST,http.status_code=200
+  - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls --tags 
http.method=POST,http.status_code=200,iserror=true

Review Comment:
   I  don't know  why use  `negative tags search` , In  order to keep this 
query `negative `, I added the query  param .
   Because the latest java agent  collect status_code ,but previous version 
didn't



##########
oap-server/server-starter/src/main/resources/ui-initialized-templates/virtual_cache/virtual-cache-root.json:
##########
@@ -0,0 +1,122 @@
+/**
+ * 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.
+ */
+
+[
+  {
+    "id": "Virtual-Cache-Root",
+    "configuration": {
+      "children": [
+        {
+          "x": 0,
+          "y": 2,
+          "w": 24,
+          "h": 52,
+          "i": "0",
+          "type": "Widget",
+          "widget": {
+            "title": "Virtual Cache"
+          },
+          "graph": {
+            "type": "ServiceList",
+            "dashboardName": "Virtual-Cache-Service",
+            "fontSize": 12,
+            "showXAxis": false,
+            "showYAxis": false,
+            "showGroup": false
+          },
+          "metrics": [
+            "cache_read_resp_time",
+            "cache_read_sla",
+            "cache_read_cpm",
+            "cache_write_resp_time",
+            "cache_write_sla",
+            "cache_write_cpm"
+          ],
+          "metricTypes": [
+            "readMetricsValues",
+            "readMetricsValues",
+            "readMetricsValues",
+            "readMetricsValues",
+            "readMetricsValues",
+            "readMetricsValues"
+          ],
+          "moved": false,
+          "metricConfig": [
+            {
+              "unit": "ms",
+              "label": "Read Latency",
+              "calculation": "average"
+            },
+            {
+              "label": "Successful Read Rate",
+              "unit": "%",
+              "calculation": "percentageAvg"
+            },
+            {
+              "label": "Read Traffic",
+              "unit": "calls / min",
+              "calculation": "average"
+            },
+            {
+              "unit": "ms",
+              "label": "Write Latency",
+              "calculation": "average"
+            },
+            {
+              "label": "Successful Write Rate",
+              "unit": "%",
+              "calculation": "percentageAvg"
+            },
+            {
+              "label": "Write Traffic",
+              "unit": "calls / min",
+              "calculation": "average"
+            }
+          ]
+        },
+        {
+          "x": 0,
+          "y": 0,
+          "w": 24,
+          "h": 2,
+          "i": "100",
+          "type": "Text",
+          "metricTypes": [
+            ""
+          ],
+          "metrics": [
+            ""
+          ],
+          "graph": {
+            "fontColor": "blue",
+            "backgroundColor": "white",
+            "content": "Observe the Virtual Cache which is conjectured by 
language agent through various plugins.",
+            "fontSize": 14,
+            "textAlign": "left",
+            "url": 
"https://skywalking.apache.org/docs/main/latest/en/setup/service-agent/virtual-cache/";
+          },
+          "moved": false
+        }
+      ],
+      "id": "Virtual-Cache-Root",
+      "layer": "VIRTUAL_CACHE",
+      "entity": "All",
+      "name": "Virtual-Cache-Root",
+      "isRoot": true

Review Comment:
   The UI code I updated:
   
   
![image](https://user-images.githubusercontent.com/3917424/190854261-5b628507-d17a-4cb8-ba62-203f8222ffc8.png)
   
   The screenshot
   
   
![image](https://user-images.githubusercontent.com/3917424/190854745-e4310aed-4c21-4d84-9cfd-779443272ac2.png)
   
   
![image](https://user-images.githubusercontent.com/3917424/190854868-14a72390-1e12-4921-b4ee-a68044bd66b0.png)
   
   
   
   



##########
oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/AnalyzerModuleConfig.java:
##########
@@ -60,6 +62,23 @@ public class AnalyzerModuleConfig extends ModuleConfig {
     @Setter
     @Getter
     private DBLatencyThresholdsAndWatcher dbLatencyThresholdsAndWatcher;
+
+    @Setter
+    @Getter
+    private String slowCacheWriteThreshold = "default:20";
+
+    @Setter
+    @Getter
+    private CacheWriteLatencyThresholdsAndWatcher 
cacheWriteLatencyThresholdsAndWatcher;
+
+    @Setter
+    @Getter
+    private String slowCacheReadThreshold = "default:20";
+
+    @Setter
+    @Getter
+    private CacheReadLatencyThresholdsAndWatcher 
cacheReadLatencyThresholdsAndWatcher;

Review Comment:
   Will be done 



##########
oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/vservice/VirtualCacheProcessor.java:
##########
@@ -0,0 +1,158 @@
+/*
+ * 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.analyzer.provider.trace.parser.listener.vservice;
+
+import com.google.gson.Gson;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanLayer;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
+import org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleConfig;
+import 
org.apache.skywalking.oap.server.analyzer.provider.trace.parser.SpanTags;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
+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.config.NamingControl;
+import org.apache.skywalking.oap.server.core.source.ServiceMeta;
+import org.apache.skywalking.oap.server.core.source.Source;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowWrite;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheWrite;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RequiredArgsConstructor
+public class VirtualCacheProcessor implements VirtualServiceProcessor {
+
+    private final NamingControl namingControl;
+
+    private final AnalyzerModuleConfig config;
+
+    private final List<Source> sourceList = new ArrayList<>();
+
+    @Override
+    public void prepareVSIfNecessary(SpanObject span, SegmentObject 
segmentObject) {
+        if (span.getSpanLayer() != SpanLayer.Cache) {
+            return;
+        }
+        Map<String, String> tags = span.getTagsList().stream()

Review Comment:
   Maybe we would have more virtual service  in future .We already have two at 
least now 



##########
oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/vservice/VirtualCacheProcessor.java:
##########
@@ -0,0 +1,158 @@
+/*
+ * 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.analyzer.provider.trace.parser.listener.vservice;
+
+import com.google.gson.Gson;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanLayer;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
+import org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleConfig;
+import 
org.apache.skywalking.oap.server.analyzer.provider.trace.parser.SpanTags;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
+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.config.NamingControl;
+import org.apache.skywalking.oap.server.core.source.ServiceMeta;
+import org.apache.skywalking.oap.server.core.source.Source;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowWrite;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheWrite;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RequiredArgsConstructor
+public class VirtualCacheProcessor implements VirtualServiceProcessor {
+
+    private final NamingControl namingControl;
+
+    private final AnalyzerModuleConfig config;
+
+    private final List<Source> sourceList = new ArrayList<>();
+
+    @Override
+    public void prepareVSIfNecessary(SpanObject span, SegmentObject 
segmentObject) {
+        if (span.getSpanLayer() != SpanLayer.Cache) {
+            return;
+        }
+        Map<String, String> tags = span.getTagsList().stream()

Review Comment:
   > you make every processor implementations iterate span's tags by themselves.
   
   The premise is matching a SpanLayer . 
   
   I think one class for a virtual service , it's clear . Like above I said , A 
processor must math a SpanLayer for reducing repeated logical calculation .
   
   BTW , initial virtual database was written int `RPCAnalysisListener` , I 
think it's a  little chaotic . 



##########
test/e2e-v2/cases/storage/storage-cases.yaml:
##########
@@ -47,7 +47,7 @@ cases:
   - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls
     expected: expected/traces-list.yml
   # negative tags search: relationship should be logical AND instead of 
logical OR
-  - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls --tags 
http.method=POST,http.status_code=200
+  - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls --tags 
http.method=POST,http.status_code=200,iserror=true

Review Comment:
   I don't know why use negative tags search , In order to keep this query 
negative , I added the query param .
   Because the latest java agent collect all  status_code ,but previous agent 
collect the status_code which max than 400 .
   You could find this PR  https://github.com/apache/skywalking-java/pull/258
   
   
   



##########
test/e2e-v2/script/env:
##########
@@ -25,4 +25,4 @@ 
SW_KUBERNETES_COMMIT_SHA=0f3ec68e5a7e1608cec8688716b848ed15e971e5
 SW_ROVER_COMMIT=d956eaede57b62108b78bca48045bd09ba88e653
 SW_BANYANDB_COMMIT=5a326d7e36a008c5ea10e3ae506309cb29733c53
 
-SW_CTL_COMMIT=a7c4ccae106e4a5a0b6296f860396f289444058d
+SW_CTL_COMMIT=fd9b93348f51655ec58046aa645cc127c68bbdd2

Review Comment:
   My mistake . Sorry .



##########
test/e2e-v2/cases/storage/storage-cases.yaml:
##########
@@ -47,7 +47,7 @@ cases:
   - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls
     expected: expected/traces-list.yml
   # negative tags search: relationship should be logical AND instead of 
logical OR
-  - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls --tags 
http.method=POST,http.status_code=200
+  - query: swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls --tags 
http.method=POST,http.status_code=200,iserror=true

Review Comment:
   BTW  I updated `SW_AGENT_JAVA_COMMIT` to the latest  



##########
test/e2e-v2/cases/meter/meter-cases.yaml:
##########
@@ -31,4 +31,50 @@
         curl -s -XPOST http://${sender_host}:${sender_9093}/sendBatchMetrics > 
/dev/null;
         sleep 10;
         swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql metrics linear 
--name=batch_test --instance-name=test-instance --service-name=test-service |yq 
e 'to_entries' -
-      expected: expected/metrics-has-value.yml
\ No newline at end of file
+      expected: expected/metrics-has-value.yml
+    # virtual cache
+    - query: |
+        swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql metrics linear 
--name=cache_read_resp_time  --service-id=R3VhdmFDYWNoZS1sb2NhbA==.0  | yq e 
'to_entries' -
+      expected: expected/metrics-has-value0.yml
+    - query: |
+        swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql metrics linear 
--name=cache_read_sla  --service-id=R3VhdmFDYWNoZS1sb2NhbA==.0  | yq e 
'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql metrics linear 
--name=cache_read_cpm  --service-id=R3VhdmFDYWNoZS1sb2NhbA==.0  | yq e 
'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql metrics multiple-linear 
--name=cache_read_percentile  --service-id=R3VhdmFDYWNoZS1sb2NhbA==.0  | yq e 
'to_entries | with(.[] ; .value=(.value | to_entries))' -
+      expected: expected/metrics-has-value-percentile.yml

Review Comment:
   I  think `Test ` should as possible as complete. In order to inspect a 
project ,`Test` should cover all code ideally such as unit test.



##########
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java:
##########
@@ -163,18 +168,18 @@ private static final void addNewScope(ScopeDeclaration 
declaration, Class origin
         int id = declaration.id();
         if (ID_2_NAME.containsKey(id)) {
             throw new UnexpectedException(
-                "ScopeDeclaration id=" + id + " at " + originalClass.getName() 
+ " has conflict with another named " + ID_2_NAME
-                    .get(id));
+                    "ScopeDeclaration id=" + id + " at " + 
originalClass.getName() + " has conflict with another named " + ID_2_NAME
+                            .get(id));

Review Comment:
   Could you help me to set appropriate format settings ?  Maybe provide me a 
doc or an  exported settings .
    I'm pained for the setting ,Thanks 



##########
oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/trace/parser/listener/vservice/VirtualCacheProcessor.java:
##########
@@ -0,0 +1,158 @@
+/*
+ * 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.analyzer.provider.trace.parser.listener.vservice;
+
+import com.google.gson.Gson;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
+import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanLayer;
+import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
+import org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleConfig;
+import 
org.apache.skywalking.oap.server.analyzer.provider.trace.parser.SpanTags;
+import org.apache.skywalking.oap.server.core.analysis.IDManager;
+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.config.NamingControl;
+import org.apache.skywalking.oap.server.core.source.ServiceMeta;
+import org.apache.skywalking.oap.server.core.source.Source;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowRead;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheSlowWrite;
+import org.apache.skywalking.oap.server.core.source.VirtualCacheWrite;
+import org.apache.skywalking.oap.server.library.util.StringUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RequiredArgsConstructor
+public class VirtualCacheProcessor implements VirtualServiceProcessor {
+
+    private final NamingControl namingControl;
+
+    private final AnalyzerModuleConfig config;
+
+    private final List<Source> sourceList = new ArrayList<>();
+
+    @Override
+    public void prepareVSIfNecessary(SpanObject span, SegmentObject 
segmentObject) {
+        if (span.getSpanLayer() != SpanLayer.Cache) {
+            return;
+        }
+        Map<String, String> tags = span.getTagsList().stream()
+                .collect(Collectors.toMap(KeyStringValuePair::getKey, 
KeyStringValuePair::getValue));
+        if (!(tags.containsKey(SpanTags.CACHE_KEY) && 
tags.containsKey(SpanTags.CACHE_OP) && tags.containsKey(SpanTags.CACHE_CMD) && 
tags.containsKey(SpanTags.CACHE_TYPE))) {
+            return;
+        }
+        String cacheType = tags.get(SpanTags.CACHE_TYPE).toLowerCase();
+        String peer = span.getPeer();
+        // peer is blank if it's a local span
+        if (StringUtil.isBlank(peer)) {
+            peer = tags.get(SpanTags.CACHE_TYPE) + "-local";
+        }
+        long timeBucket = TimeBucket.getMinuteTimeBucket(span.getStartTime());
+        String serviceName = namingControl.formatServiceName(peer);
+        int latency = (int) (span.getEndTime() - span.getStartTime());
+        if (latency > 0) {
+            log.info("latency data : {}", new Gson().toJson(span));

Review Comment:
   I  would remove this log . 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to