diff --git a/apm-protocol/apm-network/src/main/proto b/apm-protocol/apm-network/src/main/proto index bd1f91f7e1..385fb8b005 160000 --- a/apm-protocol/apm-network/src/main/proto +++ b/apm-protocol/apm-network/src/main/proto @@ -1 +1 @@ -Subproject commit bd1f91f7e1cb4de9d9b5ccb71f36ce6b1c7c97f5 +Subproject commit 385fb8b0057b98c9350f7a94d228b977f5154d4b diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md index 7f392efdd9..dbf0a69f14 100644 --- a/docs/en/changes/changes.md +++ b/docs/en/changes/changes.md @@ -13,8 +13,6 @@ source tar from the website and publish them to your private maven repository. * [Breaking Change] Remove H2 as storage option permanently. BanyanDB 0.8(OAP 10.2 required) is easy, stable and production-ready. Don't need H2 as default storage anymore. -* Support `labelAvg` function in the OAL engine. -* Added `maxLabelCount` parameter in the `labelCount` function of OAL to limit the number of labels can be counted. #### OAP Server @@ -56,6 +54,9 @@ * Fix `AvgHistogramPercentileFunction` doesn't have proper field definition for `ranks`. * BanyanDB: Support the new Property data module. * MQE: Support `top_n_of` function for merging multiple metrics topn query. +* Support `labelAvg` function in the OAL engine. +* Added `maxLabelCount` parameter in the `labelCount` function of OAL to limit the number of labels can be counted. +* Adapt the new Browser API(`/browser/perfData/webVitals`, `/browser/perfData/resources`) protocol. #### UI @@ -78,6 +79,7 @@ * Optimize Trace Profiling widget. * Implement Async Profiling widget. * Fix inaccurate data query issue on endpoint topology page. +* Update browser dashboard for the new metrics. #### Documentation * Update release document to adopt newly added revision-based process. diff --git a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4 b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4 index ccb6cd74d5..6ddd83d600 100644 --- a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4 +++ b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4 @@ -73,6 +73,8 @@ SRC_BROWSER_APP_SINGLE_VERSION_PERF: 'BrowserAppSingleVersionPerf'; SRC_BROWSER_APP_TRAFFIC: 'BrowserAppTraffic'; SRC_BROWSER_APP_PAGE_TRAFFIC: 'BrowserAppPageTraffic'; SRC_BROWSER_APP_SINGLE_VERSION_TRAFFIC: 'BrowserAppSingleVersionTraffic'; +SRC_BROWSER_APP_RESOURCE_PERF: 'BrowserAppResourcePerf'; +SRC_BROWSER_APP_WEB_VITALS_PERF: 'BrowserAppWebVitalsPerf'; // Constructors symbols diff --git a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4 b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4 index e78a3102da..f1ec8c4045 100644 --- a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4 +++ b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4 @@ -59,7 +59,7 @@ source SRC_SERVICE_INSTANCE_CLR_CPU | SRC_SERVICE_INSTANCE_CLR_GC | SRC_SERVICE_INSTANCE_CLR_THREAD | SRC_SERVICE_INSTANCE_JVM_CPU | SRC_SERVICE_INSTANCE_JVM_MEMORY | SRC_SERVICE_INSTANCE_JVM_MEMORY_POOL | SRC_SERVICE_INSTANCE_JVM_GC | SRC_SERVICE_INSTANCE_JVM_THREAD | SRC_SERVICE_INSTANCE_JVM_CLASS |// JVM source of service instance SRC_ENVOY_INSTANCE_METRIC | - SRC_BROWSER_APP_PERF | SRC_BROWSER_APP_PAGE_PERF | SRC_BROWSER_APP_SINGLE_VERSION_PERF | + SRC_BROWSER_APP_PERF | SRC_BROWSER_APP_PAGE_PERF | SRC_BROWSER_APP_SINGLE_VERSION_PERF | SRC_BROWSER_APP_RESOURCE_PERF | SRC_BROWSER_APP_WEB_VITALS_PERF | SRC_BROWSER_APP_TRAFFIC | SRC_BROWSER_APP_PAGE_TRAFFIC | SRC_BROWSER_APP_SINGLE_VERSION_TRAFFIC | SRC_EVENT | SRC_MQ_ACCESS | SRC_MQ_ENDPOINT_ACCESS | SRC_K8S_SERVICE | SRC_K8S_SERVICE_INSTANCE | SRC_K8S_ENDPOINT | SRC_K8S_SERVICE_RELATION | SRC_K8S_SERVICE_INSTANCE_RELATION | diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/manual/endpoint/BrowserAppPageTrafficDispatcher.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/manual/endpoint/BrowserAppPageTrafficDispatcher.java index 8df13e6f1e..443a1ddcfb 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/manual/endpoint/BrowserAppPageTrafficDispatcher.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/manual/endpoint/BrowserAppPageTrafficDispatcher.java @@ -30,6 +30,7 @@ public class BrowserAppPageTrafficDispatcher extends BrowserAppTrafficSourceDisp traffic.setTimeBucket(source.getTimeBucket()); traffic.setName(source.getName()); traffic.setServiceId(source.getServiceId()); + traffic.setLastPingTimestamp(source.getTimeBucket()); MetricsStreamProcessor.getInstance().in(traffic); } } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/source/BrowserAppResourcePerf.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/source/BrowserAppResourcePerf.java new file mode 100644 index 0000000000..cda18af2e0 --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/source/BrowserAppResourcePerf.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.browser.source; + +import lombok.Getter; +import lombok.Setter; +import org.apache.skywalking.oap.server.core.analysis.IDManager; +import org.apache.skywalking.oap.server.core.source.ScopeDeclaration; +import org.apache.skywalking.oap.server.core.source.ScopeDefaultColumn; +import org.apache.skywalking.oap.server.core.source.Source; + +import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_RESOURCE_PERF; +import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.ENDPOINT_CATALOG_NAME; + +@ScopeDeclaration(id = BROWSER_APP_RESOURCE_PERF, name = "BrowserAppResourcePerf", catalog = ENDPOINT_CATALOG_NAME) +@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class) +@Setter +@Getter +public class BrowserAppResourcePerf extends Source { + + @Override + public int scope() { + return BROWSER_APP_RESOURCE_PERF; + } + + @Override + public String getEntityId() { + return IDManager.EndpointID.buildId(serviceId, path); + } + + @ScopeDefaultColumn.DefinedByField(columnName = "service_id") + @ScopeDefaultColumn.BanyanDB(groupByCondInTopN = true) + private String serviceId; + @ScopeDefaultColumn.DefinedByField(columnName = "service_name", requireDynamicActive = true) + private String serviceName; + private String path; + private String name; + private int duration; + private int size; + private String protocol; + private String type; + + @Override + public void prepare() { + serviceId = IDManager.ServiceID.buildId(serviceName, true); + } +} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/source/BrowserAppWebVitalsPerf.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/source/BrowserAppWebVitalsPerf.java new file mode 100644 index 0000000000..95c003596c --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/browser/source/BrowserAppWebVitalsPerf.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.core.browser.source; + +import lombok.Getter; +import lombok.Setter; +import org.apache.skywalking.oap.server.core.analysis.IDManager; +import org.apache.skywalking.oap.server.core.source.ScopeDeclaration; +import org.apache.skywalking.oap.server.core.source.ScopeDefaultColumn; +import org.apache.skywalking.oap.server.core.source.Source; + +import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_WEB_VITALS_PAGE_PERF; +import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.ENDPOINT_CATALOG_NAME; + +@ScopeDeclaration(id = BROWSER_APP_WEB_VITALS_PAGE_PERF, name = "BrowserAppWebVitalsPerf", catalog = ENDPOINT_CATALOG_NAME) +@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class) +@Setter +@Getter +public class BrowserAppWebVitalsPerf extends Source { + + @Override + public int scope() { + return BROWSER_APP_WEB_VITALS_PAGE_PERF; + } + + @Override + public String getEntityId() { + return IDManager.EndpointID.buildId(serviceId, path); + } + + @ScopeDefaultColumn.DefinedByField(columnName = "service_id") + @ScopeDefaultColumn.BanyanDB(groupByCondInTopN = true) + private String serviceId; + @ScopeDefaultColumn.DefinedByField(columnName = "service_name", requireDynamicActive = true) + private String serviceName; + private String path; + private int fmpTime; + private int clsTime; + private int lcpTime; + + @Override + public void prepare() { + serviceId = IDManager.ServiceID.buildId(serviceName, true); + } +} diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java index 88595ad457..15eed04799 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java @@ -147,6 +147,9 @@ public class DefaultScopeDefine { public static final int ASYNC_PROFILER_TASK = 85; public static final int ASYNC_PROFILER_TASK_LOG = 86; + public static final int BROWSER_APP_WEB_VITALS_PAGE_PERF = 87; + public static final int BROWSER_APP_RESOURCE_PERF = 88; + /** * Catalog of scope, the metrics processor could use this to group all generated metrics by oal rt. */ diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/BrowserModuleProvider.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/BrowserModuleProvider.java index d7e6dd074b..2ee5969356 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/BrowserModuleProvider.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/BrowserModuleProvider.java @@ -36,7 +36,12 @@ import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlo import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.listener.ErrorLogRecordListener; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.listener.MultiScopesErrorLogAnalysisListener; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.PerfDataParserListenerManager; -import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.MultiScopesPerfDataAnalysisListener; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDataDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserResourcePerfDataDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserWebVitalsPerfDataDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.BrowserPerfDataAnalysisListener; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.BrowserWebResourcePerfDataAnalysisListener; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.BrowserWebVitalsPerfDataAnalysisListener; import org.apache.skywalking.oap.server.receiver.sharing.server.SharingServerModule; import org.apache.skywalking.oap.server.telemetry.TelemetryModule; @@ -117,9 +122,10 @@ public class BrowserModuleProvider extends ModuleProvider { } private PerfDataParserListenerManager perfDataListenerManager() { - PerfDataParserListenerManager listenerManager = new PerfDataParserListenerManager(); - listenerManager.add(new MultiScopesPerfDataAnalysisListener.Factory(getManager(), moduleConfig)); - + PerfDataParserListenerManager listenerManager = new PerfDataParserListenerManager(getManager(), moduleConfig); + listenerManager.add(BrowserPerfDataDecorator.class, new BrowserPerfDataAnalysisListener.Factory(getManager(), moduleConfig)); + listenerManager.add(BrowserWebVitalsPerfDataDecorator.class, new BrowserWebVitalsPerfDataAnalysisListener.Factory(getManager(), moduleConfig)); + listenerManager.add(BrowserResourcePerfDataDecorator.class, new BrowserWebResourcePerfDataAnalysisListener.Factory(getManager(), moduleConfig)); return listenerManager; } diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/grpc/BrowserPerfServiceHandler.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/grpc/BrowserPerfServiceHandler.java index 61f55f848b..f9fe795a17 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/grpc/BrowserPerfServiceHandler.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/grpc/BrowserPerfServiceHandler.java @@ -23,13 +23,18 @@ import org.apache.skywalking.apm.network.common.v3.Commands; import org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog; import org.apache.skywalking.apm.network.language.agent.v3.BrowserPerfData; import org.apache.skywalking.apm.network.language.agent.v3.BrowserPerfServiceGrpc; +import org.apache.skywalking.apm.network.language.agent.v3.BrowserResourcePerfData; +import org.apache.skywalking.apm.network.language.agent.v3.BrowserWebVitalsPerfData; import org.apache.skywalking.oap.server.library.module.ModuleManager; import org.apache.skywalking.oap.server.library.server.grpc.GRPCHandler; import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.ErrorLogAnalyzer; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.ErrorLogParserListenerManager; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDataDecorator; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.PerfDataAnalyzer; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.PerfDataParserListenerManager; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserResourcePerfDataDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserWebVitalsPerfDataDecorator; import org.apache.skywalking.oap.server.telemetry.TelemetryModule; import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics; import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics; @@ -95,8 +100,46 @@ public class BrowserPerfServiceHandler extends BrowserPerfServiceGrpc.BrowserPer } HistogramMetrics.Timer timer = perfHistogram.createTimer(); try { - PerfDataAnalyzer analyzer = new PerfDataAnalyzer(moduleManager, perfDataListenerManager, config); - analyzer.doAnalysis(request); + PerfDataAnalyzer analyzer = new PerfDataAnalyzer(perfDataListenerManager); + analyzer.doAnalysis(new BrowserPerfDataDecorator(request)); + } catch (Throwable e) { + log.error(e.getMessage(), e); + perfErrorCounter.inc(); + } finally { + timer.finish(); + responseObserver.onNext(Commands.newBuilder().build()); + responseObserver.onCompleted(); + } + } + + @Override + public void collectResourcePerfData(BrowserResourcePerfData request, StreamObserver responseObserver) { + if (log.isDebugEnabled()) { + log.debug("receive browser resource performance data"); + } + HistogramMetrics.Timer timer = perfHistogram.createTimer(); + try { + PerfDataAnalyzer analyzer = new PerfDataAnalyzer(perfDataListenerManager); + analyzer.doAnalysis(new BrowserResourcePerfDataDecorator(request)); + } catch (Throwable e) { + log.error(e.getMessage(), e); + perfErrorCounter.inc(); + } finally { + timer.finish(); + responseObserver.onNext(Commands.newBuilder().build()); + responseObserver.onCompleted(); + } + } + + @Override + public void collectWebVitalsPerfData(BrowserWebVitalsPerfData request, StreamObserver responseObserver) { + if (log.isDebugEnabled()) { + log.debug("receive browser web vitals performance data"); + } + HistogramMetrics.Timer timer = perfHistogram.createTimer(); + try { + PerfDataAnalyzer analyzer = new PerfDataAnalyzer(perfDataListenerManager); + analyzer.doAnalysis(new BrowserWebVitalsPerfDataDecorator(request)); } catch (Throwable e) { log.error(e.getMessage(), e); perfErrorCounter.inc(); diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/rest/BrowserPerfServiceHTTPHandler.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/rest/BrowserPerfServiceHTTPHandler.java index cd55a9adaa..203ba75ee8 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/rest/BrowserPerfServiceHTTPHandler.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/handler/rest/BrowserPerfServiceHTTPHandler.java @@ -23,12 +23,17 @@ import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.apm.network.common.v3.Commands; import org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog; import org.apache.skywalking.apm.network.language.agent.v3.BrowserPerfData; +import org.apache.skywalking.apm.network.language.agent.v3.BrowserResourcePerfData; +import org.apache.skywalking.apm.network.language.agent.v3.BrowserWebVitalsPerfData; import org.apache.skywalking.oap.server.library.module.ModuleManager; import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.ErrorLogAnalyzer; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.ErrorLogParserListenerManager; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDataDecorator; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.PerfDataAnalyzer; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.PerfDataParserListenerManager; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserResourcePerfDataDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserWebVitalsPerfDataDecorator; import org.apache.skywalking.oap.server.telemetry.TelemetryModule; import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics; import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics; @@ -116,8 +121,37 @@ public class BrowserPerfServiceHTTPHandler { @Post("/browser/perfData") public Commands collectPerfData(final BrowserPerfData browserPerfData) { try (HistogramMetrics.Timer ignored = perfHistogram.createTimer()) { - final PerfDataAnalyzer analyzer = new PerfDataAnalyzer(moduleManager, perfDataListenerManager, config); - analyzer.doAnalysis(browserPerfData); + final PerfDataAnalyzer analyzer = new PerfDataAnalyzer(perfDataListenerManager); + analyzer.doAnalysis(new BrowserPerfDataDecorator(browserPerfData)); + return Commands.newBuilder().build(); + } catch (Throwable e) { + log.error(e.getMessage(), e); + perfErrorCounter.inc(); + throw e; + } + } + + @Post("/browser/perfData/webVitals") + public Commands collectWebVitalsPerfData(final BrowserWebVitalsPerfData browserPerfData) { + try (HistogramMetrics.Timer ignored = perfHistogram.createTimer()) { + final PerfDataAnalyzer analyzer = new PerfDataAnalyzer(perfDataListenerManager); + analyzer.doAnalysis(new BrowserWebVitalsPerfDataDecorator(browserPerfData)); + return Commands.newBuilder().build(); + } catch (Throwable e) { + log.error(e.getMessage(), e); + perfErrorCounter.inc(); + throw e; + } + } + + @Post("/browser/perfData/resources") + public Commands collectResourcesPerfData(final List resourceList) { + try (HistogramMetrics.Timer ignored = perfHistogram.createTimer()) { + resourceList.stream().filter(resource -> resource.getDuration() > 0 && resource.getSize() > 0) + .forEach(resource -> { + final PerfDataAnalyzer analyzer = new PerfDataAnalyzer(perfDataListenerManager); + analyzer.doAnalysis(new BrowserResourcePerfDataDecorator(resource)); + }); return Commands.newBuilder().build(); } catch (Throwable e) { log.error(e.getMessage(), e); diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataAnalyzer.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataAnalyzer.java index f39a948025..4926638996 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataAnalyzer.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataAnalyzer.java @@ -17,33 +17,25 @@ package org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance; -import java.util.LinkedList; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.apm.network.language.agent.v3.BrowserPerfData; -import org.apache.skywalking.oap.server.library.module.ModuleManager; import org.apache.skywalking.oap.server.library.util.StringUtil; -import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDecorator; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.PerfDataAnalysisListener; @Slf4j @RequiredArgsConstructor public class PerfDataAnalyzer { - private final ModuleManager moduleManager; - private final PerfDataParserListenerManager listenerManager; - private final BrowserServiceModuleConfig config; + private final PerfDataParserListenerManager factory; - private final List analysisListeners = new LinkedList<>(); - - public void doAnalysis(BrowserPerfData browserPerfData) { - if (StringUtil.isBlank(browserPerfData.getService())) { + @SuppressWarnings("unchecked") + public void doAnalysis(T decorator) { + if (StringUtil.isBlank(decorator.getService())) { return; } - createAnalysisListeners(); + final PerfDataAnalysisListener listener = (PerfDataAnalysisListener) factory.create(decorator.getClass()); - BrowserPerfDataDecorator decorator = new BrowserPerfDataDecorator(browserPerfData); // Use the server side current time. long nowMillis = System.currentTimeMillis(); decorator.setTime(nowMillis); @@ -56,21 +48,8 @@ public class PerfDataAnalyzer { decorator.setPagePath("/"); } - notifyListener(decorator); - - notifyListenerToBuild(); + listener.parse(decorator); + listener.build(); } - private void notifyListener(BrowserPerfDataDecorator decorator) { - analysisListeners.forEach(listener -> listener.parse(decorator)); - } - - private void notifyListenerToBuild() { - analysisListeners.forEach(PerfDataAnalysisListener::build); - } - - private void createAnalysisListeners() { - listenerManager.getPerfDataListenerFactories() - .forEach(factory -> analysisListeners.add(factory.create(moduleManager, config))); - } } diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataParserListenerManager.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataParserListenerManager.java index 46b8ae7182..e8d714e698 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataParserListenerManager.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/PerfDataParserListenerManager.java @@ -6,27 +6,45 @@ * (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 + * 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.receiver.browser.provider.parser.performance; -import java.util.ArrayList; -import java.util.List; -import lombok.Getter; +import org.apache.skywalking.oap.server.library.module.ModuleManager; +import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.PerfDataAnalysisListener; import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.PerfDataListenerFactory; -public class PerfDataParserListenerManager { - @Getter - private final List perfDataListenerFactories = new ArrayList<>(); +import java.util.HashMap; +import java.util.Map; - public void add(final PerfDataListenerFactory factory) { - perfDataListenerFactories.add(factory); +public class PerfDataParserListenerManager { + + private final Map, PerfDataListenerFactory> factories = new HashMap<>(); + + private final ModuleManager moduleManager; + private final BrowserServiceModuleConfig config; + + public PerfDataParserListenerManager(ModuleManager moduleManager, BrowserServiceModuleConfig config) { + this.moduleManager = moduleManager; + this.config = config; + } + + public void add(Class decoratorClass, PerfDataListenerFactory factory) { + factories.put(decoratorClass, factory); + } + + @SuppressWarnings("unchecked") + public PerfDataAnalysisListener create(Class decorator) { + return factories.get(decorator).create(moduleManager, config); } } diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/BrowserPerfDataDecorator.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserPerfDataDecorator.java similarity index 96% rename from oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/BrowserPerfDataDecorator.java rename to oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserPerfDataDecorator.java index 119c6f3229..14f3c1697a 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/BrowserPerfDataDecorator.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserPerfDataDecorator.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance; +package org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators; import org.apache.skywalking.apm.network.language.agent.v3.BrowserPerfData; -public class BrowserPerfDataDecorator { +public class BrowserPerfDataDecorator implements BrowserPerfDecorator { private BrowserPerfData.Builder builder; public BrowserPerfDataDecorator(final BrowserPerfData browserPerfData) { diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserPerfDecorator.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserPerfDecorator.java new file mode 100644 index 0000000000..62f5dc4e4a --- /dev/null +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserPerfDecorator.java @@ -0,0 +1,33 @@ +/* + * 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.receiver.browser.provider.parser.performance.decorators; + +public interface BrowserPerfDecorator { + String getService(); + + void setTime(long time); + + String getServiceVersion(); + + void setServiceVersion(String serviceVersion); + + String getPagePath(); + + void setPagePath(String pagePath); +} diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserResourcePerfDataDecorator.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserResourcePerfDataDecorator.java new file mode 100644 index 0000000000..516345d728 --- /dev/null +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserResourcePerfDataDecorator.java @@ -0,0 +1,83 @@ +/* + * 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.receiver.browser.provider.parser.performance.decorators; + +import org.apache.skywalking.apm.network.language.agent.v3.BrowserResourcePerfData; + +public class BrowserResourcePerfDataDecorator implements BrowserPerfDecorator { + private final BrowserResourcePerfData.Builder builder; + + public BrowserResourcePerfDataDecorator(BrowserResourcePerfData builder) { + this.builder = builder.toBuilder(); + } + + @Override + public String getService() { + return builder.getService(); + } + + @Override + public void setTime(long time) { + builder.setTime(time); + } + + @Override + public String getServiceVersion() { + return builder.getServiceVersion(); + } + + @Override + public void setServiceVersion(String serviceVersion) { + builder.setServiceVersion(serviceVersion); + } + + @Override + public String getPagePath() { + return builder.getPagePath(); + } + + @Override + public void setPagePath(String pagePath) { + builder.setPagePath(pagePath); + } + + public String getName() { + return builder.getName(); + } + + public int getDuration() { + return builder.getDuration(); + } + + public int getSize() { + return builder.getSize(); + } + + public String getProtocol() { + return builder.getProtocol(); + } + + public String getType() { + return builder.getResourceType(); + } + + public long getTime() { + return builder.getTime(); + } +} diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserWebVitalsPerfDataDecorator.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserWebVitalsPerfDataDecorator.java new file mode 100644 index 0000000000..7d4ede1f23 --- /dev/null +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/decorators/BrowserWebVitalsPerfDataDecorator.java @@ -0,0 +1,75 @@ +/* + * 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.receiver.browser.provider.parser.performance.decorators; + +import org.apache.skywalking.apm.network.language.agent.v3.BrowserWebVitalsPerfData; + +public class BrowserWebVitalsPerfDataDecorator implements BrowserPerfDecorator { + private BrowserWebVitalsPerfData.Builder builder; + + public BrowserWebVitalsPerfDataDecorator(BrowserWebVitalsPerfData builder) { + this.builder = builder.toBuilder(); + } + + @Override + public String getService() { + return builder.getService(); + } + + @Override + public void setTime(long time) { + builder.setTime(time); + } + + @Override + public String getServiceVersion() { + return builder.getServiceVersion(); + } + + @Override + public void setServiceVersion(String serviceVersion) { + builder.setServiceVersion(serviceVersion); + } + + @Override + public String getPagePath() { + return builder.getPagePath(); + } + + @Override + public void setPagePath(String pagePath) { + builder.setPagePath(pagePath); + } + + public long getTime() { + return builder.getTime(); + } + + public int getFmpTime() { + return builder.getFmpTime(); + } + + public int getLcpTime() { + return builder.getLcpTime(); + } + + public int getClsTime() { + return builder.getClsTime(); + } +} diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/MultiScopesPerfDataAnalysisListener.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserPerfDataAnalysisListener.java similarity index 86% rename from oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/MultiScopesPerfDataAnalysisListener.java rename to oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserPerfDataAnalysisListener.java index 4aed69033c..60695237c9 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/MultiScopesPerfDataAnalysisListener.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserPerfDataAnalysisListener.java @@ -24,21 +24,21 @@ import org.apache.skywalking.oap.server.core.config.NamingControl; import org.apache.skywalking.oap.server.core.source.SourceReceiver; import org.apache.skywalking.oap.server.library.module.ModuleManager; import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; -import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.BrowserPerfDataDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDataDecorator; /** * Browser traffic and page Performance related metrics. */ @Slf4j -public class MultiScopesPerfDataAnalysisListener implements PerfDataAnalysisListener { +public class BrowserPerfDataAnalysisListener implements PerfDataAnalysisListener { private final SourceReceiver sourceReceiver; - private final SourceBuilder sourceBuilder; + private final BrowserPerfDataSourceBuilder sourceBuilder; - public MultiScopesPerfDataAnalysisListener(final SourceReceiver sourceReceiver, - final NamingControl namingControl) { + public BrowserPerfDataAnalysisListener(final SourceReceiver sourceReceiver, + final NamingControl namingControl) { this.sourceReceiver = sourceReceiver; - this.sourceBuilder = new SourceBuilder(namingControl); + this.sourceBuilder = new BrowserPerfDataSourceBuilder(namingControl); } /** @@ -85,7 +85,7 @@ public class MultiScopesPerfDataAnalysisListener implements PerfDataAnalysisList sourceBuilder.setFmpTime(decorator.getFmpTime()); } - public static class Factory implements PerfDataListenerFactory { + public static class Factory implements PerfDataListenerFactory { private final SourceReceiver sourceReceiver; private final NamingControl namingControl; @@ -101,9 +101,9 @@ public class MultiScopesPerfDataAnalysisListener implements PerfDataAnalysisList } @Override - public PerfDataAnalysisListener create(final ModuleManager moduleManager, + public PerfDataAnalysisListener create(final ModuleManager moduleManager, final BrowserServiceModuleConfig moduleConfig) { - return new MultiScopesPerfDataAnalysisListener(sourceReceiver, namingControl); + return new BrowserPerfDataAnalysisListener(sourceReceiver, namingControl); } } } diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/SourceBuilder.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserPerfDataSourceBuilder.java similarity index 99% rename from oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/SourceBuilder.java rename to oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserPerfDataSourceBuilder.java index 7d50ea4561..b3a87d90e0 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/SourceBuilder.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserPerfDataSourceBuilder.java @@ -36,7 +36,7 @@ import org.apache.skywalking.oap.server.core.source.Source; * Browser traffic and performance related source. */ @RequiredArgsConstructor -class SourceBuilder { +class BrowserPerfDataSourceBuilder { private final NamingControl namingControl; @Getter diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserWebResourcePerfDataAnalysisListener.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserWebResourcePerfDataAnalysisListener.java new file mode 100644 index 0000000000..c8195df136 --- /dev/null +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserWebResourcePerfDataAnalysisListener.java @@ -0,0 +1,78 @@ +/* + * 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.receiver.browser.provider.parser.performance.listener; + +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.analysis.TimeBucket; +import org.apache.skywalking.oap.server.core.browser.source.BrowserAppResourcePerf; +import org.apache.skywalking.oap.server.core.config.NamingControl; +import org.apache.skywalking.oap.server.core.source.SourceReceiver; +import org.apache.skywalking.oap.server.library.module.ModuleManager; +import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserResourcePerfDataDecorator; + +public class BrowserWebResourcePerfDataAnalysisListener implements PerfDataAnalysisListener { + private final SourceReceiver sourceReceiver; + private final NamingControl namingControl; + private BrowserAppResourcePerf browserAppResourcePerf; + + public BrowserWebResourcePerfDataAnalysisListener(SourceReceiver sourceReceiver, NamingControl namingControl) { + this.sourceReceiver = sourceReceiver; + this.namingControl = namingControl; + } + + @Override + public void build() { + sourceReceiver.receive(browserAppResourcePerf); + } + + @Override + public void parse(BrowserResourcePerfDataDecorator decorator) { + browserAppResourcePerf = new BrowserAppResourcePerf(); + browserAppResourcePerf.setTimeBucket(TimeBucket.getMinuteTimeBucket(decorator.getTime())); + browserAppResourcePerf.setServiceName(namingControl.formatServiceName(decorator.getService())); + browserAppResourcePerf.setPath(namingControl.formatEndpointName(browserAppResourcePerf.getServiceName(), decorator.getPagePath())); + browserAppResourcePerf.setName(decorator.getName()); + browserAppResourcePerf.setDuration(decorator.getDuration()); + browserAppResourcePerf.setSize(decorator.getSize()); + browserAppResourcePerf.setProtocol(decorator.getProtocol()); + browserAppResourcePerf.setType(decorator.getType()); + } + + public static class Factory implements PerfDataListenerFactory { + + private final SourceReceiver sourceReceiver; + private final NamingControl namingControl; + + public Factory(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig) { + this.sourceReceiver = moduleManager.find(CoreModule.NAME) + .provider() + .getService(SourceReceiver.class); + + this.namingControl = moduleManager.find(CoreModule.NAME) + .provider() + .getService(NamingControl.class); + } + + @Override + public PerfDataAnalysisListener create(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig) { + return new BrowserWebResourcePerfDataAnalysisListener(sourceReceiver, namingControl); + } + } +} diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserWebVitalsPerfDataAnalysisListener.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserWebVitalsPerfDataAnalysisListener.java new file mode 100644 index 0000000000..db7c6cd19a --- /dev/null +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/BrowserWebVitalsPerfDataAnalysisListener.java @@ -0,0 +1,76 @@ +/* + * 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.receiver.browser.provider.parser.performance.listener; + +import org.apache.skywalking.oap.server.core.CoreModule; +import org.apache.skywalking.oap.server.core.analysis.TimeBucket; +import org.apache.skywalking.oap.server.core.browser.source.BrowserAppWebVitalsPerf; +import org.apache.skywalking.oap.server.core.config.NamingControl; +import org.apache.skywalking.oap.server.core.source.SourceReceiver; +import org.apache.skywalking.oap.server.library.module.ModuleManager; +import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserWebVitalsPerfDataDecorator; + +public class BrowserWebVitalsPerfDataAnalysisListener implements PerfDataAnalysisListener { + private final SourceReceiver sourceReceiver; + private final NamingControl namingControl; + private BrowserAppWebVitalsPerf browserAppWebVitalsPerf; + + public BrowserWebVitalsPerfDataAnalysisListener(SourceReceiver sourceReceiver, NamingControl namingControl) { + this.sourceReceiver = sourceReceiver; + this.namingControl = namingControl; + } + + @Override + public void build() { + sourceReceiver.receive(browserAppWebVitalsPerf); + } + + @Override + public void parse(BrowserWebVitalsPerfDataDecorator decorator) { + browserAppWebVitalsPerf = new BrowserAppWebVitalsPerf(); + browserAppWebVitalsPerf.setTimeBucket(TimeBucket.getMinuteTimeBucket(decorator.getTime())); + browserAppWebVitalsPerf.setServiceName(namingControl.formatServiceName(decorator.getService())); + browserAppWebVitalsPerf.setPath(namingControl.formatEndpointName(browserAppWebVitalsPerf.getServiceName(), decorator.getPagePath())); + browserAppWebVitalsPerf.setFmpTime(decorator.getFmpTime()); + browserAppWebVitalsPerf.setClsTime(decorator.getClsTime()); + browserAppWebVitalsPerf.setLcpTime(decorator.getLcpTime()); + } + + public static class Factory implements PerfDataListenerFactory { + + private final SourceReceiver sourceReceiver; + private final NamingControl namingControl; + + public Factory(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig) { + this.sourceReceiver = moduleManager.find(CoreModule.NAME) + .provider() + .getService(SourceReceiver.class); + + this.namingControl = moduleManager.find(CoreModule.NAME) + .provider() + .getService(NamingControl.class); + } + + @Override + public PerfDataAnalysisListener create(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig) { + return new BrowserWebVitalsPerfDataAnalysisListener(sourceReceiver, namingControl); + } + } +} diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataAnalysisListener.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataAnalysisListener.java index b5a45742e5..f9c95809e4 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataAnalysisListener.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataAnalysisListener.java @@ -17,12 +17,12 @@ package org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener; -import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.BrowserPerfDataDecorator; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDecorator; /** * BrowserPerfDataListener represents the callback when OAP does the browser performance data analysis. */ -public interface PerfDataAnalysisListener { +public interface PerfDataAnalysisListener { /** * The last step of the analysis process. Typically, the implementations forward the analysis results to the source * receiver. @@ -32,5 +32,5 @@ public interface PerfDataAnalysisListener { /** * Parse the raw data from the probe (js-client). */ - void parse(BrowserPerfDataDecorator decorator); + void parse(T decorator); } diff --git a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataListenerFactory.java b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataListenerFactory.java index 24cd4e2f84..1de787dd19 100644 --- a/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataListenerFactory.java +++ b/oap-server/server-receiver-plugin/skywalking-browser-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/browser/provider/parser/performance/listener/PerfDataListenerFactory.java @@ -19,11 +19,12 @@ package org.apache.skywalking.oap.server.receiver.browser.provider.parser.perfor import org.apache.skywalking.oap.server.library.module.ModuleManager; import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig; +import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.decorators.BrowserPerfDecorator; /** * BrowserPerfDataListenerFactory implementation creates the listener instances when required. Every * BrowserPerfDataListener could have its own creation factory. */ -public interface PerfDataListenerFactory { - PerfDataAnalysisListener create(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig); +public interface PerfDataListenerFactory { + PerfDataAnalysisListener create(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig); } diff --git a/oap-server/server-starter/src/main/resources/oal/browser.oal b/oap-server/server-starter/src/main/resources/oal/browser.oal index 2f813ed996..5c60e5450e 100644 --- a/oap-server/server-starter/src/main/resources/oal/browser.oal +++ b/oap-server/server-starter/src/main/resources/oal/browser.oal @@ -58,6 +58,16 @@ browser_app_page_load_page_percentile = from(BrowserAppPagePerf.loadPageTime).pe browser_app_page_first_pack_percentile = from(BrowserAppPagePerf.firstPackTime).percentile2(10); browser_app_page_fmp_percentile = from(BrowserAppPagePerf.fmpTime).percentile2(10); +// Since the web vitals and resource can be load from cache or cross-origin, so the metrics should ignore when the value is 0 +browser_app_resource_duration_avg = from(BrowserAppResourcePerf.*).filter(duration > 0).labelAvg(name, duration); +browser_app_resource_size_avg = from(BrowserAppResourcePerf.*).filter(size > 0).labelAvg(name, size); +browser_app_resource_protocol_count = from(BrowserAppResourcePerf.*).labelCount(protocol); +browser_app_resource_type_count = from(BrowserAppResourcePerf.*).labelCount(type); + +browser_app_web_vitals_fmp_avg = from(BrowserAppWebVitalsPerf.fmpTime).filter(fmpTime > 0).longAvg(); +browser_app_web_vitals_cls_avg = from(BrowserAppWebVitalsPerf.clsTime).filter(clsTime > 0).longAvg(); +browser_app_web_vitals_lcp_avg = from(BrowserAppWebVitalsPerf.lcpTime).filter(lcpTime > 0).longAvg(); + // Disable unnecessary hard core stream, targeting @Stream#name ///////// //disable(browser_error_log); diff --git a/oap-server/server-starter/src/main/resources/ui-initialized-templates/browser/browser-page.json b/oap-server/server-starter/src/main/resources/ui-initialized-templates/browser/browser-page.json index 875cbdaced..fad1fd7459 100644 --- a/oap-server/server-starter/src/main/resources/ui-initialized-templates/browser/browser-page.json +++ b/oap-server/server-starter/src/main/resources/ui-initialized-templates/browser/browser-page.json @@ -63,6 +63,27 @@ }, { "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ] }, @@ -115,6 +136,27 @@ }, { "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ] }, @@ -167,6 +209,27 @@ }, { "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ] }, @@ -219,6 +282,27 @@ }, { "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ] }, @@ -271,6 +355,27 @@ }, { "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ] }, @@ -323,6 +428,27 @@ }, { "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ] }, @@ -378,6 +504,27 @@ }, { "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ], "metricConfig": [ @@ -455,6 +602,27 @@ }, { "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" } ], "metricConfig": [ @@ -471,6 +639,468 @@ "label": "ajax_error_sum" } ] + }, + { + "x": 0, + "y": 45, + "w": 8, + "h": 15, + "i": "11", + "type": "Widget", + "expressions": [ + "browser_app_web_vitals_fmp_avg" + ], + "graph": { + "type": "Line", + "step": false, + "smooth": false, + "showSymbol": true, + "showXAxis": true, + "showYAxis": true + }, + "widget": { + "title": "Web Vitals First Meaningful Paint Latency(ms)" + }, + "associate": [ + { + "widgetId": "12-0-1" + }, + { + "widgetId": "12-0-2" + }, + { + "widgetId": "12-0-3" + }, + { + "widgetId": "12-0-4" + }, + { + "widgetId": "12-0-8" + }, + { + "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" + } + ] + }, + { + "x": 8, + "y": 45, + "w": 8, + "h": 15, + "i": "12", + "type": "Widget", + "expressions": [ + "browser_app_web_vitals_cls_avg" + ], + "graph": { + "type": "Line", + "step": false, + "smooth": false, + "showSymbol": true, + "showXAxis": true, + "showYAxis": true + }, + "widget": { + "title": "Web Vitals Cumulative Layout Shift Latency(ms)" + }, + "associate": [ + { + "widgetId": "12-0-1" + }, + { + "widgetId": "12-0-2" + }, + { + "widgetId": "12-0-3" + }, + { + "widgetId": "12-0-4" + }, + { + "widgetId": "12-0-8" + }, + { + "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" + } + ] + }, + { + "x": 16, + "y": 45, + "w": 8, + "h": 15, + "i": "13", + "type": "Widget", + "expressions": [ + "browser_app_web_vitals_lcp_avg" + ], + "graph": { + "type": "Line", + "step": false, + "smooth": false, + "showSymbol": true, + "showXAxis": true, + "showYAxis": true + }, + "widget": { + "title": "Web Vitals Largest Contentful Paint Latency(ms)" + }, + "associate": [ + { + "widgetId": "12-0-1" + }, + { + "widgetId": "12-0-2" + }, + { + "widgetId": "12-0-3" + }, + { + "widgetId": "12-0-4" + }, + { + "widgetId": "12-0-8" + }, + { + "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" + } + ] + }, + { + "x": 0, + "y": 60, + "w": 6, + "h": 15, + "i": "14", + "type": "Widget", + "expressions": [ + "browser_app_resource_duration_avg" + ], + "graph": { + "type": "Line", + "step": false, + "smooth": false, + "showSymbol": true, + "showXAxis": true, + "showYAxis": true + }, + "widget": { + "title": "Load Duration(ms)" + }, + "associate": [ + { + "widgetId": "12-0-1" + }, + { + "widgetId": "12-0-2" + }, + { + "widgetId": "12-0-3" + }, + { + "widgetId": "12-0-4" + }, + { + "widgetId": "12-0-8" + }, + { + "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" + } + ] + }, + { + "x": 6, + "y": 60, + "w": 6, + "h": 15, + "i": "15", + "type": "Widget", + "expressions": [ + "browser_app_resource_size_avg/1024" + ], + "graph": { + "type": "Line", + "step": false, + "smooth": false, + "showSymbol": true, + "showXAxis": true, + "showYAxis": true + }, + "widget": { + "title": "Resource Size(KB)" + }, + "associate": [ + { + "widgetId": "12-0-1" + }, + { + "widgetId": "12-0-2" + }, + { + "widgetId": "12-0-3" + }, + { + "widgetId": "12-0-4" + }, + { + "widgetId": "12-0-8" + }, + { + "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" + } + ] + }, + { + "x": 18, + "y": 60, + "w": 6, + "h": 15, + "i": "16", + "type": "Widget", + "expressions": [ + "browser_app_resource_protocol_count" + ], + "graph": { + "type": "Line", + "step": false, + "smooth": false, + "showSymbol": true, + "showXAxis": true, + "showYAxis": true + }, + "widget": { + "title": "Resource Load Protocol Count Per Min" + }, + "associate": [ + { + "widgetId": "12-0-1" + }, + { + "widgetId": "12-0-2" + }, + { + "widgetId": "12-0-3" + }, + { + "widgetId": "12-0-4" + }, + { + "widgetId": "12-0-8" + }, + { + "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" + } + ] + }, + { + "x": 12, + "y": 60, + "w": 6, + "h": 15, + "i": "17", + "type": "Widget", + "expressions": [ + "browser_app_resource_type_count" + ], + "graph": { + "type": "Line", + "step": false, + "smooth": false, + "showSymbol": true, + "showXAxis": true, + "showYAxis": true + }, + "widget": { + "title": "Resource Type Load Count Per Min" + }, + "associate": [ + { + "widgetId": "12-0-1" + }, + { + "widgetId": "12-0-2" + }, + { + "widgetId": "12-0-3" + }, + { + "widgetId": "12-0-4" + }, + { + "widgetId": "12-0-8" + }, + { + "widgetId": "12-0-0" + }, + { + "widgetId": "12-0-10" + }, + { + "widgetId": "12-0-11" + }, + { + "widgetId": "12-0-12" + }, + { + "widgetId": "12-0-13" + }, + { + "widgetId": "12-0-14" + }, + { + "widgetId": "12-0-15" + }, + { + "widgetId": "12-0-16" + }, + { + "widgetId": "12-0-17" + } + ] } ] }, @@ -515,7 +1145,6 @@ "layer": "BROWSER", "entity": "Endpoint", "name": "Browser-Page", - "id": "Browser-Page", "isRoot": false } }