parent
15b0068fdf
commit
9143f1342d
|
|
@ -0,0 +1,108 @@
|
|||
# HTTP API Protocol
|
||||
|
||||
HTTP API Protocol defines the API data format, including api request and response data format.
|
||||
They use the HTTP1.1 wrapper of the official [SkyWalking Browser Protocol](Browser-Protocol.md). Read it for more details.
|
||||
|
||||
## Performance Data Report
|
||||
|
||||
Detail information about data format can be found in [BrowserPerf.proto](https://github.com/apache/skywalking-data-collect-protocol/blob/master/browser/BrowserPerf.proto).
|
||||
|
||||
### POST http://localhost:12800/browser/perfData
|
||||
|
||||
Send a performance data object with JSON format.
|
||||
|
||||
Input:
|
||||
|
||||
```json
|
||||
{
|
||||
"service": "web",
|
||||
"serviceVersion": "v0.0.1",
|
||||
"pagePath": "/index.html",
|
||||
"redirectTime": 10,
|
||||
"dnsTime": 10,
|
||||
"ttfbTime": 10,
|
||||
"tcpTime": 10,
|
||||
"transTime": 10,
|
||||
"domAnalysisTime": 10,
|
||||
"fptTime": 10,
|
||||
"domReadyTime": 10,
|
||||
"loadPageTime": 10,
|
||||
"resTime": 10,
|
||||
"sslTime": 10,
|
||||
"ttlTime": 10,
|
||||
"firstPackTime": 10,
|
||||
"fmpTime": 10
|
||||
}
|
||||
```
|
||||
|
||||
OutPut:
|
||||
|
||||
```json
|
||||
|
||||
```
|
||||
|
||||
## Error Log Report
|
||||
|
||||
Detail information about data format can be found in [BrowserPerf.proto](https://github.com/apache/skywalking-data-collect-protocol/blob/master/Browser/BrowserPerf.proto).
|
||||
|
||||
### POST http://localhost:12800/browser/errorLogs
|
||||
|
||||
Send an error log object list with JSON format.
|
||||
|
||||
Input:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"uniqueId": "55ec6178-3fb7-43ef-899c-a26944407b01",
|
||||
"service": "web",
|
||||
"serviceVersion": "v0.0.1",
|
||||
"pagePath": "/index.html",
|
||||
"category": "ajax",
|
||||
"message": "error",
|
||||
"line": 1,
|
||||
"col": 1,
|
||||
"stack": "error",
|
||||
"errorUrl": "/index.html"
|
||||
},
|
||||
{
|
||||
"uniqueId": "55ec6178-3fb7-43ef-899c-a26944407b02",
|
||||
"service": "web",
|
||||
"serviceVersion": "v0.0.1",
|
||||
"pagePath": "/index.html",
|
||||
"category": "ajax",
|
||||
"message": "error",
|
||||
"line": 1,
|
||||
"col": 1,
|
||||
"stack": "error",
|
||||
"errorUrl": "/index.html"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### POST http://localhost:12800/browser/errorLog
|
||||
|
||||
Send a single error log object with JSON format.
|
||||
|
||||
Input:
|
||||
|
||||
```json
|
||||
{
|
||||
"uniqueId": "55ec6178-3fb7-43ef-899c-a26944407b01",
|
||||
"service": "web",
|
||||
"serviceVersion": "v0.0.1",
|
||||
"pagePath": "/index.html",
|
||||
"category": "ajax",
|
||||
"message": "error",
|
||||
"line": 1,
|
||||
"col": 1,
|
||||
"stack": "error",
|
||||
"errorUrl": "/index.html"
|
||||
}
|
||||
```
|
||||
|
||||
OutPut:
|
||||
|
||||
```json
|
||||
|
||||
```
|
||||
|
|
@ -4,7 +4,8 @@ Browser protocol describes the data format between [skywalking-client-js](https:
|
|||
|
||||
## Overview
|
||||
|
||||
Browser protocol is defined and provided in [gRPC format](https://github.com/apache/skywalking-data-collect-protocol/blob/master/browser/BrowserPerf.proto).
|
||||
Browser protocol is defined and provided in [gRPC format](https://github.com/apache/skywalking-data-collect-protocol/blob/master/browser/BrowserPerf.proto),
|
||||
also implemented in [HTTP 1.1](Browser-HTTP-API-Protocol.md)
|
||||
|
||||
### Send performance data and error log
|
||||
|
||||
|
|
|
|||
|
|
@ -21,13 +21,17 @@ import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
|
|||
import org.apache.skywalking.oap.server.core.CoreModule;
|
||||
import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
|
||||
import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegister;
|
||||
import org.apache.skywalking.oap.server.core.server.JettyHandlerRegister;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleConfig;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleProvider;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleStartException;
|
||||
import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.module.BrowserModule;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.handler.BrowserPerfServiceHandler;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.handler.grpc.BrowserPerfServiceHandler;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.handler.rest.BrowserErrorLogReportListServletHandler;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.handler.rest.BrowserErrorLogReportSingleServletHandler;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.handler.rest.BrowserPerfDataReportServletHandler;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.ErrorLogParserListenerManager;
|
||||
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;
|
||||
|
|
@ -69,10 +73,24 @@ public class BrowserModuleProvider extends ModuleProvider {
|
|||
|
||||
GRPCHandlerRegister grpcHandlerRegister = getManager().find(SharingServerModule.NAME)
|
||||
.provider().getService(GRPCHandlerRegister.class);
|
||||
|
||||
// grpc
|
||||
grpcHandlerRegister.addHandler(
|
||||
new BrowserPerfServiceHandler(
|
||||
getManager(), moduleConfig, perfDataListenerManager(), errorLogListenerManager()));
|
||||
|
||||
// rest
|
||||
JettyHandlerRegister jettyHandlerRegister = getManager().find(SharingServerModule.NAME)
|
||||
.provider()
|
||||
.getService(JettyHandlerRegister.class);
|
||||
// performance
|
||||
jettyHandlerRegister.addHandler(
|
||||
new BrowserPerfDataReportServletHandler(getManager(), moduleConfig, perfDataListenerManager()));
|
||||
// error log
|
||||
ErrorLogParserListenerManager errorLogParserListenerManager = errorLogListenerManager();
|
||||
jettyHandlerRegister.addHandler(
|
||||
new BrowserErrorLogReportSingleServletHandler(getManager(), moduleConfig, errorLogParserListenerManager));
|
||||
jettyHandlerRegister.addHandler(
|
||||
new BrowserErrorLogReportListServletHandler(getManager(), moduleConfig, errorLogParserListenerManager));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.oap.server.receiver.browser.provider.handler;
|
||||
package org.apache.skywalking.oap.server.receiver.browser.provider.handler.grpc;
|
||||
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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.handler.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleManager;
|
||||
import org.apache.skywalking.oap.server.library.server.jetty.JettyHandler;
|
||||
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.telemetry.TelemetryModule;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.MetricsTag;
|
||||
|
||||
@Slf4j
|
||||
public abstract class BrowserErrorLogReportBaseServletHandler extends JettyHandler {
|
||||
private final ModuleManager moduleManager;
|
||||
private final BrowserServiceModuleConfig config;
|
||||
private final ErrorLogParserListenerManager errorLogListenerManager;
|
||||
|
||||
private final HistogramMetrics errorLogHistogram;
|
||||
private final CounterMetrics logErrorCounter;
|
||||
|
||||
public BrowserErrorLogReportBaseServletHandler(ModuleManager moduleManager,
|
||||
BrowserServiceModuleConfig config,
|
||||
ErrorLogParserListenerManager errorLogListenerManager) {
|
||||
this.moduleManager = moduleManager;
|
||||
this.config = config;
|
||||
this.errorLogListenerManager = errorLogListenerManager;
|
||||
|
||||
MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME)
|
||||
.provider()
|
||||
.getService(MetricsCreator.class);
|
||||
|
||||
errorLogHistogram = metricsCreator.createHistogramMetric(
|
||||
"browser_error_log_in_latency", "The process latency of browser error log", new MetricsTag.Keys("protocol"),
|
||||
new MetricsTag.Values("grpc")
|
||||
);
|
||||
logErrorCounter = metricsCreator.createCounter(
|
||||
"browser_error_log_analysis_error_count", "The error number of browser error log analysis",
|
||||
new MetricsTag.Keys("protocol"), new MetricsTag.Values("http")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(final HttpServletRequest req,
|
||||
final HttpServletResponse resp) throws ServletException, IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(final HttpServletRequest req,
|
||||
final HttpServletResponse resp) throws ServletException, IOException {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("receive browser error log");
|
||||
}
|
||||
|
||||
HistogramMetrics.Timer timer = errorLogHistogram.createTimer();
|
||||
try {
|
||||
for (BrowserErrorLog browserErrorLog : parseBrowserErrorLog(req)) {
|
||||
ErrorLogAnalyzer analyzer = new ErrorLogAnalyzer(moduleManager, errorLogListenerManager, config);
|
||||
analyzer.doAnalysis(browserErrorLog);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
log.error(e.getMessage(), e);
|
||||
logErrorCounter.inc();
|
||||
} finally {
|
||||
timer.finish();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract List<BrowserErrorLog> parseBrowserErrorLog(HttpServletRequest request) throws IOException;
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* 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.handler.rest;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleManager;
|
||||
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.ErrorLogParserListenerManager;
|
||||
|
||||
public class BrowserErrorLogReportListServletHandler extends BrowserErrorLogReportBaseServletHandler {
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
public BrowserErrorLogReportListServletHandler(final ModuleManager moduleManager,
|
||||
final BrowserServiceModuleConfig config,
|
||||
final ErrorLogParserListenerManager errorLogListenerManager) {
|
||||
super(moduleManager, config, errorLogListenerManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<BrowserErrorLog> parseBrowserErrorLog(final HttpServletRequest request) throws IOException {
|
||||
BufferedReader reader = request.getReader();
|
||||
String line;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
final JsonArray array = gson.fromJson(stringBuilder.toString(), JsonArray.class);
|
||||
if (array.size() == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final ArrayList<BrowserErrorLog> errorLogs = new ArrayList<>(array.size());
|
||||
for (JsonElement element : array) {
|
||||
BrowserErrorLog.Builder builder = BrowserErrorLog.newBuilder();
|
||||
ProtoBufJsonUtils.fromJSON(element.toString(), builder);
|
||||
errorLogs.add(builder.build());
|
||||
}
|
||||
return errorLogs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pathSpec() {
|
||||
return "/browser/errorLogs";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.handler.rest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleManager;
|
||||
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.ErrorLogParserListenerManager;
|
||||
|
||||
public class BrowserErrorLogReportSingleServletHandler extends BrowserErrorLogReportBaseServletHandler {
|
||||
public BrowserErrorLogReportSingleServletHandler(final ModuleManager moduleManager,
|
||||
final BrowserServiceModuleConfig config,
|
||||
final ErrorLogParserListenerManager errorLogListenerManager) {
|
||||
super(moduleManager, config, errorLogListenerManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<BrowserErrorLog> parseBrowserErrorLog(final HttpServletRequest request) throws IOException {
|
||||
BufferedReader reader = request.getReader();
|
||||
String line;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
|
||||
BrowserErrorLog.Builder builder = BrowserErrorLog.newBuilder();
|
||||
ProtoBufJsonUtils.fromJSON(stringBuilder.toString(), builder);
|
||||
return Collections.singletonList(builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pathSpec() {
|
||||
return "/browser/errorLog";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.oap.server.receiver.browser.provider.handler.rest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
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.server.jetty.JettyHandler;
|
||||
import org.apache.skywalking.oap.server.library.util.ProtoBufJsonUtils;
|
||||
import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig;
|
||||
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.telemetry.TelemetryModule;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.MetricsTag;
|
||||
|
||||
@Slf4j
|
||||
public class BrowserPerfDataReportServletHandler extends JettyHandler {
|
||||
private final ModuleManager moduleManager;
|
||||
private final BrowserServiceModuleConfig config;
|
||||
private final PerfDataParserListenerManager perfDataListenerManager;
|
||||
|
||||
private final HistogramMetrics perfHistogram;
|
||||
private final CounterMetrics perfErrorCounter;
|
||||
|
||||
public BrowserPerfDataReportServletHandler(ModuleManager moduleManager,
|
||||
BrowserServiceModuleConfig config,
|
||||
PerfDataParserListenerManager perfDataListenerManager) {
|
||||
this.moduleManager = moduleManager;
|
||||
this.config = config;
|
||||
this.perfDataListenerManager = perfDataListenerManager;
|
||||
|
||||
MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME)
|
||||
.provider()
|
||||
.getService(MetricsCreator.class);
|
||||
|
||||
perfHistogram = metricsCreator.createHistogramMetric(
|
||||
"browser_perf_data_in_latency", "The process latency of browser performance data",
|
||||
new MetricsTag.Keys("protocol"), new MetricsTag.Values("http")
|
||||
);
|
||||
perfErrorCounter = metricsCreator.createCounter(
|
||||
"browser_perf_data_analysis_error_count", "The error number of browser performance data analysis",
|
||||
new MetricsTag.Keys("protocol"), new MetricsTag.Values("http")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(final HttpServletRequest req,
|
||||
final HttpServletResponse resp) throws ServletException, IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(final HttpServletRequest req,
|
||||
final HttpServletResponse resp) throws ServletException, IOException {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("receive browser performance data");
|
||||
}
|
||||
|
||||
HistogramMetrics.Timer timer = perfHistogram.createTimer();
|
||||
try {
|
||||
BrowserPerfData browserPerfData = parseBrowserPerfData(req);
|
||||
PerfDataAnalyzer analyzer = new PerfDataAnalyzer(moduleManager, perfDataListenerManager, config);
|
||||
analyzer.doAnalysis(browserPerfData);
|
||||
} catch (Throwable e) {
|
||||
log.error(e.getMessage(), e);
|
||||
perfErrorCounter.inc();
|
||||
} finally {
|
||||
timer.finish();
|
||||
}
|
||||
}
|
||||
|
||||
protected BrowserPerfData parseBrowserPerfData(HttpServletRequest request) throws IOException {
|
||||
BufferedReader reader = request.getReader();
|
||||
String line;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
|
||||
BrowserPerfData.Builder builder = BrowserPerfData.newBuilder();
|
||||
ProtoBufJsonUtils.fromJSON(stringBuilder.toString(), builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pathSpec() {
|
||||
return "/browser/perfData";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* 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.handler.rest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
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.ErrorCategory;
|
||||
import org.apache.skywalking.oap.server.library.module.ModuleManager;
|
||||
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
|
||||
import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
|
||||
import org.apache.skywalking.oap.server.telemetry.none.MetricsCreatorNoop;
|
||||
import org.apache.skywalking.oap.server.telemetry.none.NoneTelemetryProvider;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.internal.util.reflection.Whitebox;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PowerMockIgnore({"javax.management.*"})
|
||||
public class BrowserReportServletHandlerTest {
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
@Mock
|
||||
private ModuleManager moduleManager;
|
||||
@Mock
|
||||
private NoneTelemetryProvider telemetryProvider;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
Mockito.when(telemetryProvider.getService(MetricsCreator.class))
|
||||
.thenReturn(new MetricsCreatorNoop());
|
||||
|
||||
TelemetryModule telemetryModule = Mockito.spy(TelemetryModule.class);
|
||||
Whitebox.setInternalState(telemetryModule, "loadedProvider", telemetryProvider);
|
||||
Mockito.when(moduleManager.find(TelemetryModule.NAME)).thenReturn(telemetryModule);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPerfData() throws IOException {
|
||||
final String json = "{\n" +
|
||||
" \"service\": \"test\",\n" +
|
||||
" \"serviceVersion\": \"v0.0.1\",\n" +
|
||||
" \"pagePath\": \"/e2e-browser\",\n" +
|
||||
" \"redirectTime\": 1,\n" +
|
||||
" \"dnsTime\": 2,\n" +
|
||||
" \"ttfbTime\": 3,\n" +
|
||||
" \"tcpTime\": 4,\n" +
|
||||
" \"transTime\": 5,\n" +
|
||||
" \"domAnalysisTime\": 6,\n" +
|
||||
" \"fptTime\": 7,\n" +
|
||||
" \"domReadyTime\": 8,\n" +
|
||||
" \"loadPageTime\": 9,\n" +
|
||||
" \"resTime\": 10,\n" +
|
||||
" \"sslTime\": 11,\n" +
|
||||
" \"ttlTime\": 12,\n" +
|
||||
" \"firstPackTime\": 13,\n" +
|
||||
" \"fmpTime\": 14\n" +
|
||||
"}";
|
||||
final BrowserPerfDataReportServletHandler reportServletHandler = new BrowserPerfDataReportServletHandler(
|
||||
moduleManager, null, null);
|
||||
|
||||
when(request.getReader()).thenReturn(
|
||||
new BufferedReader(new StringReader(json)));
|
||||
final BrowserPerfData result = reportServletHandler.parseBrowserPerfData(request);
|
||||
Assert.assertEquals("test", result.getService());
|
||||
Assert.assertEquals("v0.0.1", result.getServiceVersion());
|
||||
Assert.assertEquals("/e2e-browser", result.getPagePath());
|
||||
Assert.assertEquals(1, result.getRedirectTime());
|
||||
Assert.assertEquals(2, result.getDnsTime());
|
||||
Assert.assertEquals(3, result.getTtfbTime());
|
||||
Assert.assertEquals(4, result.getTcpTime());
|
||||
Assert.assertEquals(5, result.getTransTime());
|
||||
Assert.assertEquals(6, result.getDomAnalysisTime());
|
||||
Assert.assertEquals(7, result.getFptTime());
|
||||
Assert.assertEquals(8, result.getDomReadyTime());
|
||||
Assert.assertEquals(9, result.getLoadPageTime());
|
||||
Assert.assertEquals(10, result.getResTime());
|
||||
Assert.assertEquals(11, result.getSslTime());
|
||||
Assert.assertEquals(12, result.getTtlTime());
|
||||
Assert.assertEquals(13, result.getFirstPackTime());
|
||||
Assert.assertEquals(14, result.getFmpTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorLogSingle() throws IOException {
|
||||
final String singleJson = "{\n" +
|
||||
" \"uniqueId\": \"55ec6178-3fb7-43ef-899c-a26944407b0e\",\n" +
|
||||
" \"service\": \"test\",\n" +
|
||||
" \"serviceVersion\": \"v0.0.1\",\n" +
|
||||
" \"pagePath\": \"/e2e-browser\",\n" +
|
||||
" \"category\": \"ajax\",\n" +
|
||||
" \"message\": \"test\",\n" +
|
||||
" \"line\": 1,\n" +
|
||||
" \"col\": 1,\n" +
|
||||
" \"stack\": \"e2e\",\n" +
|
||||
" \"errorUrl\": \"/e2e-browser\"\n" +
|
||||
"}";
|
||||
|
||||
final BrowserErrorLogReportSingleServletHandler singleServletHandler = new BrowserErrorLogReportSingleServletHandler(
|
||||
moduleManager, null, null);
|
||||
|
||||
when(request.getReader()).thenReturn(
|
||||
new BufferedReader(new StringReader(singleJson)));
|
||||
final List<BrowserErrorLog> browserErrorLogs = singleServletHandler.parseBrowserErrorLog(request);
|
||||
Assert.assertEquals(1, browserErrorLogs.size());
|
||||
BrowserErrorLog errorLog = browserErrorLogs.get(0);
|
||||
Assert.assertEquals("55ec6178-3fb7-43ef-899c-a26944407b0e", errorLog.getUniqueId());
|
||||
Assert.assertEquals("test", errorLog.getService());
|
||||
Assert.assertEquals("v0.0.1", errorLog.getServiceVersion());
|
||||
Assert.assertEquals("/e2e-browser", errorLog.getPagePath());
|
||||
Assert.assertEquals(ErrorCategory.ajax, errorLog.getCategory());
|
||||
Assert.assertEquals("test", errorLog.getMessage());
|
||||
Assert.assertEquals(1, errorLog.getLine());
|
||||
Assert.assertEquals(1, errorLog.getCol());
|
||||
Assert.assertEquals("e2e", errorLog.getStack());
|
||||
Assert.assertEquals("/e2e-browser", errorLog.getErrorUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testErrorLogList() throws IOException {
|
||||
final String listJson = "[\n" +
|
||||
" {\n" +
|
||||
" \"uniqueId\": \"55ec6178-3fb7-43ef-899c-a26944407b01\",\n" +
|
||||
" \"service\": \"test\",\n" +
|
||||
" \"serviceVersion\": \"v0.0.1\",\n" +
|
||||
" \"pagePath\": \"/e2e-browser\",\n" +
|
||||
" \"category\": \"ajax\",\n" +
|
||||
" \"message\": \"test\",\n" +
|
||||
" \"line\": 1,\n" +
|
||||
" \"col\": 1,\n" +
|
||||
" \"stack\": \"e2e\",\n" +
|
||||
" \"errorUrl\": \"/e2e-browser\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"uniqueId\": \"55ec6178-3fb7-43ef-899c-a26944407b02\",\n" +
|
||||
" \"service\": \"test\",\n" +
|
||||
" \"serviceVersion\": \"v0.0.1\",\n" +
|
||||
" \"pagePath\": \"/e2e-browser\",\n" +
|
||||
" \"category\": \"ajax\",\n" +
|
||||
" \"message\": \"test\",\n" +
|
||||
" \"line\": 1,\n" +
|
||||
" \"col\": 1,\n" +
|
||||
" \"stack\": \"e2e\",\n" +
|
||||
" \"errorUrl\": \"/e2e-browser\"\n" +
|
||||
" }\n" +
|
||||
"]";
|
||||
|
||||
final BrowserErrorLogReportListServletHandler listServletHandler = new BrowserErrorLogReportListServletHandler(
|
||||
moduleManager, null, null);
|
||||
|
||||
when(request.getReader()).thenReturn(
|
||||
new BufferedReader(new StringReader(listJson)));
|
||||
|
||||
final List<BrowserErrorLog> browserErrorLogs = listServletHandler.parseBrowserErrorLog(request);
|
||||
Assert.assertEquals(2, browserErrorLogs.size());
|
||||
BrowserErrorLog errorLog1 = browserErrorLogs.get(0);
|
||||
Assert.assertEquals("55ec6178-3fb7-43ef-899c-a26944407b01", errorLog1.getUniqueId());
|
||||
Assert.assertEquals("test", errorLog1.getService());
|
||||
Assert.assertEquals("v0.0.1", errorLog1.getServiceVersion());
|
||||
Assert.assertEquals("/e2e-browser", errorLog1.getPagePath());
|
||||
Assert.assertEquals(ErrorCategory.ajax, errorLog1.getCategory());
|
||||
Assert.assertEquals("test", errorLog1.getMessage());
|
||||
Assert.assertEquals(1, errorLog1.getLine());
|
||||
Assert.assertEquals(1, errorLog1.getCol());
|
||||
Assert.assertEquals("e2e", errorLog1.getStack());
|
||||
Assert.assertEquals("/e2e-browser", errorLog1.getErrorUrl());
|
||||
BrowserErrorLog errorLog2 = browserErrorLogs.get(1);
|
||||
Assert.assertEquals("55ec6178-3fb7-43ef-899c-a26944407b02", errorLog2.getUniqueId());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue