Support new browser metrics upload API (#12948)

This commit is contained in:
mrproliu 2025-01-09 21:52:20 +08:00 committed by GitHub
parent 3c52eedd04
commit 3232b54752
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 1265 additions and 68 deletions

@ -1 +1 @@
Subproject commit bd1f91f7e1cb4de9d9b5ccb71f36ce6b1c7c97f5
Subproject commit 385fb8b0057b98c9350f7a94d228b977f5154d4b

View File

@ -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.

View File

@ -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

View File

@ -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 |

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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.
*/

View File

@ -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;
}

View File

@ -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<Commands> 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<Commands> 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();

View File

@ -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<BrowserResourcePerfData> 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);

View File

@ -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<PerfDataAnalysisListener> analysisListeners = new LinkedList<>();
public void doAnalysis(BrowserPerfData browserPerfData) {
if (StringUtil.isBlank(browserPerfData.getService())) {
@SuppressWarnings("unchecked")
public <T extends BrowserPerfDecorator> void doAnalysis(T decorator) {
if (StringUtil.isBlank(decorator.getService())) {
return;
}
createAnalysisListeners();
final PerfDataAnalysisListener<T> listener = (PerfDataAnalysisListener<T>) 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)));
}
}

View File

@ -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<PerfDataListenerFactory> 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<Class<?>, 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 <T extends BrowserPerfDecorator> void add(Class<T> decoratorClass, PerfDataListenerFactory<T> factory) {
factories.put(decoratorClass, factory);
}
@SuppressWarnings("unchecked")
public <T extends BrowserPerfDecorator> PerfDataAnalysisListener<T> create(Class<T> decorator) {
return factories.get(decorator).create(moduleManager, config);
}
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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<BrowserPerfDataDecorator> {
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<BrowserPerfDataDecorator> {
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<BrowserPerfDataDecorator> create(final ModuleManager moduleManager,
final BrowserServiceModuleConfig moduleConfig) {
return new MultiScopesPerfDataAnalysisListener(sourceReceiver, namingControl);
return new BrowserPerfDataAnalysisListener(sourceReceiver, namingControl);
}
}
}

View File

@ -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

View File

@ -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<BrowserResourcePerfDataDecorator> {
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<BrowserResourcePerfDataDecorator> {
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<BrowserResourcePerfDataDecorator> create(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig) {
return new BrowserWebResourcePerfDataAnalysisListener(sourceReceiver, namingControl);
}
}
}

View File

@ -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<BrowserWebVitalsPerfDataDecorator> {
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<BrowserWebVitalsPerfDataDecorator> {
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<BrowserWebVitalsPerfDataDecorator> create(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig) {
return new BrowserWebVitalsPerfDataAnalysisListener(sourceReceiver, namingControl);
}
}
}

View File

@ -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<T extends BrowserPerfDecorator> {
/**
* 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);
}

View File

@ -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<T extends BrowserPerfDecorator> {
PerfDataAnalysisListener<T> create(ModuleManager moduleManager, BrowserServiceModuleConfig moduleConfig);
}

View File

@ -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);

View File

@ -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
}
}