未验证 提交 7ef8b3e4 编写于 作者: Z zhang-wei 提交者: GitHub

Support Browser protocol at OAP (#4228)

上级 6b6e4d76
# 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.
name: E2E
on:
pull_request:
push:
branches:
- master
tags:
- 'v*'
env:
SKIP_TEST: true
jobs:
JavaScriptClient:
name: Java Script Client
runs-on: ubuntu-latest
strategy:
matrix:
storage: ['h2', 'mysql', 'es6', 'es7', 'influxdb']
env:
SW_STORAGE: ${{ matrix.storage }}
steps:
- uses: actions/checkout@v2
- name: checkout submodules
shell: bash
run: |
git submodule sync --recursive
git -c protocol.version=2 submodule update --init --force --recursive --depth=1
- name: Compile and Build
run: make docker && ES_VERSION=es7 TAG=latest-es7 make docker
- name: Copy dist package
run: cp -R dist test/e2e/
- name: Browser Receiver ${{ matrix.storage }}
run: ./mvnw --batch-mode -f test/e2e/pom.xml -am -DfailIfNoTests=false verify -Dit.test=org.apache.skywalking.e2e.browser.BrowserE2E
- uses: actions/upload-artifact@v1
if: failure()
with:
name: logs
path: logs
\ No newline at end of file
......@@ -28,7 +28,7 @@ The core features are following.
- Distributed tracing and context propagation
- Database access metrics. Detect slow database access statements(including SQL statements).
- Alarm
- Browser performance monitoring
<img src="http://skywalking.apache.org/assets/frame-v8.jpg?u=20200423"/>
......
......@@ -66,6 +66,8 @@ If you are already familiar with SkyWalking, you could use this catalog to find
* [Plugin development guide](en/setup/service-agent/java-agent/README.md#plugin-development-guide).
* [Agent plugin tests and performance tests](en/setup/service-agent/java-agent/README.md#test).
* [Other language agents](en/setup/README.md#language-agents-in-service) includes Nginx LUA, Python, .NetCore, PHP, NodeJS, Go.
* Browser performance monitoring
* Track the performance of the browser, such as latency of redirect, dns, ttfb. For more information, [click here](https://github.com/apache/skywalking-client-js).
* Service Mesh
* [SkyWalking on Istio](en/setup/istio/README.md). Introduces how to use Istio Mixer bypass Adapter to work with SkyWalking.
* Use [ALS (access log service)](https://www.envoyproxy.io/docs/envoy/latest/api-v2/service/accesslog/v2/als.proto) to observe service mesh, without Mixer. Follow [document](en/setup/envoy/als_setting.md) to open it.
......
......@@ -53,6 +53,12 @@ In this case, input are request of each ServiceInstanceJVMCPU scope, avg is base
> endpoint_percent = from(Endpoint.*).percent(status == true);
In this case, all input are requests of each endpoint, condition is `endpoint.status == true`.
- `rate`. The rate expressed as a fraction of 100, for the condition matched input.
> browser_app_error_rate = from(BrowserAppTraffic.*).rate(trafficCategory == BrowserAppTrafficCategory.FIRST_ERROR, trafficCategory == BrowserAppTrafficCategory.NORMAL);
In this case, all input are requests of each browser app traffic, `numerator` condition is `trafficCategory == BrowserAppTrafficCategory.FIRST_ERROR` and `denominator` condition is `trafficCategory == BrowserAppTrafficCategory.NORMAL`.
The parameter (1) is the `numerator` condition.
The parameter (2) is the `denominator` condition.
- `sum`. The sum calls per scope entity.
> service_calls_sum = from(Service.*).sum();
......
......@@ -19,8 +19,8 @@ Calculate the metrics data from each request of the service.
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the service | yes | int |
| name | Represent the name of the service | | string |
| nodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | enum |
| serviceInstanceName | Represent the name of the service instance id referred | | string |
| endpointName | Represent the name of the endpoint, such a full path of HTTP URI | | string |
| latency | Represent how much time of each request. | | int |
......@@ -34,9 +34,9 @@ Calculate the metrics data from each request of the service instance.
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the service instance, usually a number. | yes | int |
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `processId@Service name` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `uuid@ipv4` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| serviceName | Represent the name of the service. | | string |
| nodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | enum |
| endpointName | Represent the name of the endpoint, such a full path of HTTP URI. | | string|
| latency | Represent how much time of each request. | | int |
| status | Represent whether success or fail of the request. | | bool(true for success) |
......@@ -51,8 +51,7 @@ Calculate the metrics data if the service instance is a JVM and collected by jav
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the service instance, usually a number. | yes | int |
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `processId@Service name` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `uuid@ipv4` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| serviceName | Represent the name of the service. | | string |
| usePercent | Represent how much percent of cpu time cost| | double|
......@@ -60,8 +59,7 @@ Calculate the metrics data if the service instance is a JVM and collected by jav
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the service instance, usually a number. | yes | int |
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `processId@Service name` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `uuid@ipv4` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| serviceName | Represent the name of the service. | | string |
| heapStatus | Represent this value the memory metrics values are heap or not | | bool |
| init | See JVM document | | long |
......@@ -73,8 +71,7 @@ Calculate the metrics data if the service instance is a JVM and collected by jav
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the service instance, usually a number. | yes | int |
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `processId@Service name` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `uuid@ipv4` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| serviceName | Represent the name of the service. | | string |
| poolType | Include CODE_CACHE_USAGE, NEWGEN_USAGE, OLDGEN_USAGE, SURVIVOR_USAGE, PERMGEN_USAGE, METASPACE_USAGE based on different version of JVM. | | enum |
| init | See JVM document | | long |
......@@ -86,8 +83,7 @@ Calculate the metrics data if the service instance is a JVM and collected by jav
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the service instance, usually a number. | yes | int |
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `processId@Service name` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `uuid@ipv4` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| serviceName | Represent the name of the service. | | string |
| phrase | Include NEW and OLD | | Enum |
| time | GC time cost | | long |
......@@ -97,8 +93,7 @@ Calculate the metrics data if the service instance is a JVM and collected by jav
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the service instance, usually a number. | yes | int |
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `processId@Service name` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| name | Represent the name of the service instance. Such as `ip:port@Service Name`. **Notice**: current native agent uses `uuid@ipv4` as instance name, which is useless when you want to setup a filter in aggregation. | | string|
| serviceName | Represent the name of the service. | | string |
| liveCount | Represent Current number of live threads | | int |
| daemonCount | Represent Current number of daemon threads | | int |
......@@ -110,9 +105,9 @@ Calculate the metrics data from each request of the endpoint in the service.
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| id | Represent the unique id of the endpoint, usually a number. | yes | int |
| name | Represent the name of the endpoint, such a full path of HTTP URI. | | string |
| serviceName | Represent the name of the service. | | string |
| serviceNodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | enum |
| serviceInstanceName | Represent the name of the service instance id referred. | | string |
| latency | Represent how much time of each request. | | int |
| status | Represent whether success or fail of the request.| | bool(true for success) |
......@@ -125,11 +120,11 @@ Calculate the metrics data from each request between one service and the other s
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| sourceServiceId | Represent the id of the source service. | yes | int |
| sourceServiceName | Represent the name of the source service. | | string |
| sourceServiceNodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | enum |
| sourceServiceInstanceName | Represent the name of the source service instance. | | string |
| destServiceId | Represent the id of the destination service. | yes | string |
| destServiceName | Represent the name of the destination service. | | string |
| destServiceNodeType | Represent which kind of node of Service or Network address represents to. | | enum |
| destServiceInstanceName | Represent the name of the destination service instance.| | string|
| endpoint | Represent the endpoint used in this call. | | string
| componentId | Represent the id of component used in this call. | yes | string
......@@ -146,11 +141,11 @@ Calculate the metrics data from each request between one service instance and th
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| sourceServiceInstanceId | Represent the id of the source service instance. | yes | int|
| sourceServiceName | Represent the name of the source service. | | string |
| sourceServiceNodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | enum |
| sourceServiceInstanceName | Represent the name of the source service instance. | | string |
| destServiceName | Represent the name of the destination service. | | |
| destServiceInstanceId | Represent the id of the destination service instance. | yes | int|
| destServiceNodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | string |
| destServiceInstanceName | Represent the name of the destination service instance. | | string |
| endpoint | Represent the endpoint used in this call. | | string
| componentId | Represent the id of component used in this call. | yes | string
......@@ -169,13 +164,76 @@ including auto instrument agents(like Java, .NET), OpenCensus SkyWalking exporte
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| endpointId | Represent the id of the endpoint as parent in the dependency. | yes | int |
| endpoint | Represent the endpoint as parent in the dependency.| | string|
| childEndpointId | Represent the id of the endpoint being used by the parent endpoint in row(1) | yes | int|
| childEndpoint| Represent the endpoint being used by the parent endpoint in row(2) | | string |
| endpoint | Represent the endpoint as parent in the dependency.| | string|
| serviceName | Represent the name of the service. | | string |
| serviceNodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | enum |
| childEndpoint| Represent the endpoint being used by the parent endpoint in row(1) | | string |
| childServiceName | Represent the endpoint being used by the parent service in row(1) | | string |
| childServiceNodeType | Represent which kind of node of Service or Network address represents to, Such as: Normal, Database, MQ, Cache. | | string |
| childServiceInstanceName | Represent the endpoint being used by the parent service instance in row(1) | | string |
| rpcLatency | Represent the latency of the RPC from some codes in the endpoint to the childEndpoint. Exclude the latency caused by the endpoint(1) itself.
| componentId | Represent the id of component used in this call. | yes | string
| status | Represent whether success or fail of the request.| | bool(true for success) |
| responseCode | Represent the response code of HTTP response, if this request is the HTTP call. | | int |
| type | Represent the type of each request. Such as: Database, HTTP, RPC, gRPC. | | enum |
| detectPoint | Represent where is the relation detected. Values: client, server, proxy. | yes | enum|
### SCOPE `BrowserAppTraffic`
Calculate the metrics data form each request of the browser app (only browser).
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| name | Represent the browser app name of each request. | | string |
| count | Represents the number of request, fixed at 1. | | int |
| trafficCategory | Represents traffic category, Values: NORMAL, FIRST_ERROR, ERROR | | enum |
| errorCategory | Represents error category, Values: AJAX, RESOURCE, VUE, PROMISE, UNKNOWN | | enum |
### SCOPE `BrowserAppSingleVersionTraffic`
Calculate the metrics data form each request of the browser single version in the browser app (only browser).
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| name | Represent the single version name of each request. | | string |
| serviceName | Represent the name of the browser app. | | string |
| count | Represents the number of request, fixed at 1. | | int |
| trafficCategory | Represents traffic category, Values: NORMAL, FIRST_ERROR, ERROR | | enum |
| errorCategory | Represents error category, Values: AJAX, RESOURCE, VUE, PROMISE, UNKNOWN | | enum |
### SCOPE `BrowserAppPageTraffic`
Calculate the metrics data form each request of the page in the browser app (only browser).
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| name | Represent the page name of each request. | | string |
| serviceName | Represent the name of the browser app. | | string |
| count | Represents the number of request, fixed at 1. | | int |
| trafficCategory | Represents the traffic category, Values: NORMAL, FIRST_ERROR, ERROR | | enum |
| errorCategory | Represents the error category, Values: AJAX, RESOURCE, VUE, PROMISE, UNKNOWN | | enum |
### SCOPE `BrowserAppPagePerf`
Calculate the metrics data form each request of the page in the browser app (only browser).
| Name | Remarks | Group Key | Type |
|---|---|---|---|
| name | Represent the page name of each request. | | string |
| serviceName | Represent the name of the browser app. | | string |
| redirectTime | Represents the time of redirection. | | int(in ms) |
| dnsTime | Represents the DNS query time. | | int(in ms) |
| ttfbTime | Time to first Byte. | | int(in ms) |
| tcpTime | TCP connection time. | | int(in ms) |
| transTime | Content transfer time. | | int(in ms) |
| domAnalysisTime | Dom parsing time. | | int(in ms) |
| fptTime | First paint time or blank screen time. | | int(in ms) |
| domReadyTime | Dom ready time. | | int(in ms) |
| loadPageTime | Page full load time. | | int(in ms) |
| resTime | Synchronous load resources in the page. | | int(in ms) |
| sslTime | Only valid for HTTPS. | | int(in ms) |
| ttlTime | Time to interact. | | int(in ms) |
| firstPackTime | First pack time. | | int(in ms) |
| fmpTime | First Meaningful Paint. | | int(in ms) |
\ No newline at end of file
......@@ -33,6 +33,7 @@ Here is the list of all DAO interfaces in storage
1. IRegisterDAO
1. ILogQueryDAO
1. ITopNRecordsQueryDAO
1. IBrowserLogQueryDAO
## Register all service implementations
In `public void prepare()`, use `this#registerServiceImplementation` method to do register binding your implementation with the above interfaces.
......
# Browser Protocol
Browser protocol describes the data format between [skywalking-client-js](https://github.com/apache/skywalking-client-js) and backend.
## Overview
Browser protocol is defined and provided in [gRPC format](https://github.com/apache/skywalking-data-collect-protocol/blob/master/browser/BrowserPerf.proto).
### Send performance data and error log
You can send performance data and error logs via the following services:
1. `BrowserPerfService#collectPerfData` for performance data format.
1. `BrowserPerfService#collectErrorLogs` for error log format.
For error log format, there are some notices
1. `BrowserErrorLog#uniqueId` should be unique in the whole distributed environments.
......@@ -29,6 +29,12 @@ SkyWalking javaagent begins to support this since 8.0.0.
[SkyWalking Trace Data Protocol v3](Trace-Data-Protocol-v3.md) defines the communication way and format between agent and backend.
### Browser probe protocol
The browser probe, such as [skywalking-client-js](https://github.com/apache/skywalking-client-js) could use this protocol to send to backend. This service provided by gRPC.
[SkyWalking Browser Protocol](Browser-Protocol.md) define the communication way and format between `skywalking-client-js` and backend.
### Service Mesh probe protocol
The probe in sidecar or proxy could use this protocol to send data to backendEnd. This service provided by gRPC, requires
the following key info:
......
......@@ -16,6 +16,7 @@ We have following receivers, and `default` implementors are provided in our Apac
1. **receiver_jaeger**. See [details](#jaeger-receiver).
1. **receiver-oc**. See [details](#opencensus-receiver).
1. **receiver-meter**. See [details](backend-meter.md).
1. **receiver-browser**. gRPC services to accept browser performance data and error log.
The sample settings of these receivers should be already in default `application.yml`, and also list here
```yaml
......@@ -60,6 +61,10 @@ receiver_zipkin:
receiver-profile:
selector: ${SW_RECEIVER_PROFILE:default}
default:
receiver-browser:
selector: ${SW_RECEIVER_BROWSER:default}
default:
```
## gRPC/HTTP server for receiver
......
......@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.analyzer.provider.jvm;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.network.common.v3.CPU;
import org.apache.skywalking.apm.network.language.agent.v3.GC;
import org.apache.skywalking.apm.network.language.agent.v3.JVMMetric;
......@@ -38,11 +39,9 @@ import org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMMemoryPool
import org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMThread;
import org.apache.skywalking.oap.server.core.source.SourceReceiver;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Slf4j
public class JVMSourceDispatcher {
private static final Logger LOGGER = LoggerFactory.getLogger(JVMSourceDispatcher.class);
private final SourceReceiver sourceReceiver;
public JVMSourceDispatcher(ModuleManager moduleManager) {
......
......@@ -45,6 +45,14 @@ SRC_SERVICE_INSTANCE_CLR_GC: 'ServiceInstanceCLRGC';
SRC_SERVICE_INSTANCE_CLR_THREAD: 'ServiceInstanceCLRThread';
SRC_ENVOY_INSTANCE_METRIC: 'EnvoyInstanceMetric';
// Browser keywords
SRC_BROWSER_APP_PERF: 'BrowserAppPerf';
SRC_BROWSER_APP_PAGE_PERF: 'BrowserAppPagePerf';
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';
//hard code entities, only used when need to be deactived.
//Disable is targeting @Stream#name
SRC_SEGMENT: 'segment';
......@@ -61,6 +69,8 @@ SRC_PROFILE_TASK: 'profile_task';
SRC_PROFILE_TASK_LOG: 'profile_task_log';
SRC_PROFILE_THREAD_SHANPSHOT: 'profile_task_segment_snapshot';
SRC_BROWSER_ERROR_LOG: 'browser_error_log';
// Constructors symbols
DOT: '.';
......
......@@ -54,7 +54,9 @@ source
SRC_SERVICE_RELATION | SRC_SERVICE_INSTANCE_RELATION | SRC_ENDPOINT_RELATION |
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 |// JVM source of service instance
SRC_SERVICE_INSTANCE_CLR_CPU | SRC_SERVICE_INSTANCE_CLR_GC | SRC_SERVICE_INSTANCE_CLR_THREAD |
SRC_ENVOY_INSTANCE_METRIC
SRC_ENVOY_INSTANCE_METRIC |
SRC_BROWSER_APP_PERF | SRC_BROWSER_APP_PAGE_PERF | SRC_BROWSER_APP_SINGLE_VERSION_PERF |
SRC_BROWSER_APP_TRAFFIC | SRC_BROWSER_APP_PAGE_TRAFFIC | SRC_BROWSER_APP_SINGLE_VERSION_TRAFFIC
;
disableSource
......@@ -72,7 +74,7 @@ variable
;
aggregateFunction
: functionName LR_BRACKET (funcParamExpression | (literalExpression (COMMA literalExpression)?))? RR_BRACKET
: functionName LR_BRACKET ((funcParamExpression (COMMA funcParamExpression)?) | (literalExpression (COMMA literalExpression)?))? RR_BRACKET
;
functionName
......
......@@ -57,6 +57,8 @@ public class AnalysisResult {
private List<ConditionExpression> funcConditionExpressions;
private int funcConditionExpressionGetIdx = 0;
private List<Argument> funcArgs;
private int argGetIdx = 0;
......@@ -82,6 +84,10 @@ public class AnalysisResult {
funcConditionExpressions.add(conditionExpression);
}
public ConditionExpression getNextFuncConditionExpression() {
return funcConditionExpressions.get(funcConditionExpressionGetIdx++);
}
public void addFilterExpressions(Expression filterExpression) {
if (filterExpressions == null) {
filterExpressions = new LinkedList<>();
......
......@@ -31,6 +31,8 @@ import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Entranc
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.SourceFrom;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import static java.util.Objects.isNull;
public class DeepAnalysis {
public AnalysisResult analysis(AnalysisResult result) {
// 1. Set sub package name by source.metrics
......@@ -85,16 +87,20 @@ public class DeepAnalysis {
Class<?> parameterType = parameter.getType();
Annotation[] parameterAnnotations = parameter.getAnnotations();
if (parameterAnnotations == null || parameterAnnotations.length == 0) {
throw new IllegalArgumentException("Entrance method:" + entranceMethod + " doesn't include the annotation.");
throw new IllegalArgumentException(
"Entrance method:" + entranceMethod + " doesn't include the annotation.");
}
Annotation annotation = parameterAnnotations[0];
if (annotation instanceof SourceFrom) {
entryMethod.addArg(parameterType, "source." + ClassMethodUtil.toGetMethod(result.getSourceAttribute()) + "()");
entryMethod.addArg(
parameterType, "source." + ClassMethodUtil.toGetMethod(result.getSourceAttribute()) + "()");
} else if (annotation instanceof ConstOne) {
entryMethod.addArg(parameterType, "1");
} else if (annotation instanceof org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Expression) {
if (result.getFuncConditionExpressions().size() == 1) {
final ConditionExpression expression = result.getFuncConditionExpressions().get(0);
if (isNull(result.getFuncConditionExpressions()) || result.getFuncConditionExpressions().isEmpty()) {
throw new IllegalArgumentException("Entrance method:" + entranceMethod + " argument can't find funcParamExpression.");
} else {
ConditionExpression expression = result.getNextFuncConditionExpression();
final FilterMatchers.MatcherInfo matcherInfo = FilterMatchers.INSTANCE.find(expression.getExpressionType());
final String getter = matcherInfo.isBooleanType()
......@@ -107,13 +113,12 @@ public class DeepAnalysis {
argExpression.setLeft("source." + getter + "()");
entryMethod.addArg(argExpression);
} else {
throw new IllegalArgumentException("Entrance method:" + entranceMethod + " argument can't find funcParamExpression.");
}
} else if (annotation instanceof Arg) {
entryMethod.addArg(parameterType, result.getNextFuncArg());
} else {
throw new IllegalArgumentException("Entrance method:" + entranceMethod + " doesn't the expected annotation.");
throw new IllegalArgumentException(
"Entrance method:" + entranceMethod + " doesn't the expected annotation.");
}
}
......
......@@ -167,6 +167,29 @@ public class ScriptParserTest {
Assert.assertEquals("lessEqualMatch", booleanMatchExp.getExpressionType());
}
@Test
public void testParse5() throws IOException {
ScriptParser parser = ScriptParser.createFromScriptText(
"service_response_s4_summary = from(Service.latency).rate(param1 == true,param2 == false);",
TEST_SOURCE_PACKAGE
);
List<AnalysisResult> results = parser.parse().getMetricsStmts();
Assert.assertEquals(1, results.size());
AnalysisResult result = results.get(0);
Assert.assertEquals("rate", result.getAggregationFunctionName());
Assert.assertEquals(2, result.getFuncConditionExpressions().size());
ConditionExpression expression1 = result.getFuncConditionExpressions().get(0);
Assert.assertEquals("param1", expression1.getAttribute());
Assert.assertEquals("booleanMatch", expression1.getExpressionType());
Assert.assertEquals("true", expression1.getValue());
ConditionExpression expression2 = result.getFuncConditionExpressions().get(1);
Assert.assertEquals("param2", expression2.getAttribute());
Assert.assertEquals("booleanMatch", expression2.getExpressionType());
Assert.assertEquals("false", expression2.getValue());
}
@Test
public void testParse6() throws IOException {
ScriptParser parser = ScriptParser.createFromScriptText(
......
......@@ -126,6 +126,11 @@
<artifactId>skywalking-meter-receiver-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>skywalking-browser-receiver-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<!-- receiver module -->
<!-- fetcher module -->
......@@ -264,4 +269,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
\ No newline at end of file
......@@ -276,6 +276,10 @@ receiver_jaeger:
gRPCHost: ${SW_RECEIVER_JAEGER_HOST:0.0.0.0}
gRPCPort: ${SW_RECEIVER_JAEGER_PORT:14250}
receiver-browser:
selector: ${SW_RECEIVER_BROWSER:default}
default:
query:
selector: ${SW_QUERY:graphql}
graphql:
......
/*
* 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.
*
*/
// browser app
browser_app_pv = from(BrowserAppTraffic.count).filter(trafficCategory == BrowserAppTrafficCategory.NORMAL).sum();
browser_app_error_rate = from(BrowserAppTraffic.*).rate(trafficCategory == BrowserAppTrafficCategory.FIRST_ERROR,trafficCategory == BrowserAppTrafficCategory.NORMAL);
browser_app_error_sum = from(BrowserAppTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).sum();
// browser app single version
browser_app_single_version_pv = from(BrowserAppSingleVersionTraffic.count).filter(trafficCategory == BrowserAppTrafficCategory.NORMAL).sum();
browser_app_single_version_error_rate = from(BrowserAppSingleVersionTraffic.trafficCategory).rate(trafficCategory == BrowserAppTrafficCategory.FIRST_ERROR,trafficCategory == BrowserAppTrafficCategory.NORMAL);
browser_app_single_version_error_sum = from(BrowserAppSingleVersionTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).sum();
// browser app page
browser_app_page_pv = from(BrowserAppPageTraffic.count).filter(trafficCategory == BrowserAppTrafficCategory.NORMAL).sum();
browser_app_page_error_rate = from(BrowserAppPageTraffic.*).rate(trafficCategory == BrowserAppTrafficCategory.FIRST_ERROR,trafficCategory == BrowserAppTrafficCategory.NORMAL);
browser_app_page_error_sum = from(BrowserAppPageTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).sum();
browser_app_page_ajax_error_sum = from(BrowserAppPageTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).filter(errorCategory == BrowserErrorCategory.AJAX).sum();
browser_app_page_resource_error_sum = from(BrowserAppPageTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).filter(errorCategory == BrowserErrorCategory.RESOURCE).sum();
browser_app_page_js_error_sum = from(BrowserAppPageTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).filter(errorCategory in [BrowserErrorCategory.JS,BrowserErrorCategory.VUE,BrowserErrorCategory.PROMISE]).sum();
browser_app_page_unknown_error_sum = from(BrowserAppPageTraffic.count).filter(trafficCategory != BrowserAppTrafficCategory.NORMAL).filter(errorCategory == BrowserErrorCategory.UNKNOWN).sum();
// browser performance metrics
browser_app_page_redirect_avg = from(BrowserAppPagePerf.redirectTime).longAvg();
browser_app_page_dns_avg = from(BrowserAppPagePerf.dnsTime).longAvg();
browser_app_page_ttfb_avg = from(BrowserAppPagePerf.ttfbTime).longAvg();
browser_app_page_tcp_avg = from(BrowserAppPagePerf.tcpTime).longAvg();
browser_app_page_trans_avg = from(BrowserAppPagePerf.transTime).longAvg();
browser_app_page_dom_analysis_avg = from(BrowserAppPagePerf.domAnalysisTime).longAvg();
browser_app_page_fpt_avg = from(BrowserAppPagePerf.fptTime).longAvg();
browser_app_page_dom_ready_avg = from(BrowserAppPagePerf.domReadyTime).longAvg();
browser_app_page_load_page_avg = from(BrowserAppPagePerf.loadPageTime).longAvg();
browser_app_page_res_avg = from(BrowserAppPagePerf.resTime).longAvg();
browser_app_page_ssl_avg = from(BrowserAppPagePerf.sslTime).longAvg();
browser_app_page_ttl_avg = from(BrowserAppPagePerf.ttlTime).longAvg();
browser_app_page_first_pack_avg = from(BrowserAppPagePerf.firstPackTime).longAvg();
browser_app_page_fmp_avg = from(BrowserAppPagePerf.fmpTime).longAvg();
browser_app_page_fpt_percentile = from(BrowserAppPagePerf.fptTime).percentile(10);
browser_app_page_ttl_percentile = from(BrowserAppPagePerf.ttlTime).percentile(10);
browser_app_page_dom_ready_percentile = from(BrowserAppPagePerf.domReadyTime).percentile(10);
browser_app_page_load_page_percentile = from(BrowserAppPagePerf.loadPageTime).percentile(10);
browser_app_page_first_pack_percentile = from(BrowserAppPagePerf.firstPackTime).percentile(10);
browser_app_page_fmp_percentile = from(BrowserAppPagePerf.fmpTime).percentile(10);
// Disable unnecessary hard core stream, targeting @Stream#name
/////////
//disable(browser_error_log);
\ No newline at end of file
......@@ -33,6 +33,7 @@ import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
import org.apache.skywalking.oap.server.core.query.BrowserLogQueryService;
import org.apache.skywalking.oap.server.core.query.LogQueryService;
import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
......@@ -114,6 +115,7 @@ public class CoreModule extends ModuleDefine {
classes.add(AggregationQueryService.class);
classes.add(AlarmQueryService.class);
classes.add(TopNRecordsQueryService.class);
classes.add(BrowserLogQueryService.class);
}
private void addServerInterface(List<Class> classes) {
......
......@@ -52,6 +52,7 @@ import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
import org.apache.skywalking.oap.server.core.query.BrowserLogQueryService;
import org.apache.skywalking.oap.server.core.query.LogQueryService;
import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
......@@ -242,6 +243,7 @@ public class CoreModuleProvider extends ModuleProvider {
this.registerServiceImplementation(MetricsMetadataQueryService.class, new MetricsMetadataQueryService());
this.registerServiceImplementation(MetricsQueryService.class, new MetricsQueryService(getManager()));
this.registerServiceImplementation(TraceQueryService.class, new TraceQueryService(getManager()));
this.registerServiceImplementation(BrowserLogQueryService.class, new BrowserLogQueryService(getManager()));
this.registerServiceImplementation(LogQueryService.class, new LogQueryService(getManager()));
this.registerServiceImplementation(MetadataQueryService.class, new MetadataQueryService(getManager()));
this.registerServiceImplementation(AggregationQueryService.class, new AggregationQueryService(getManager()));
......
......@@ -21,6 +21,7 @@ package org.apache.skywalking.oap.server.core.analysis;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
......@@ -80,7 +81,8 @@ public class DispatcherManager implements DispatcherDetectorListener {
@Override
public void addIfAsSourceDispatcher(Class aClass) throws IllegalAccessException, InstantiationException {
if (!aClass.isInterface() && SourceDispatcher.class.isAssignableFrom(aClass)) {
if (!aClass.isInterface() && !Modifier.isAbstract(
aClass.getModifiers()) && SourceDispatcher.class.isAssignableFrom(aClass)) {
Type[] genericInterfaces = aClass.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
ParameterizedType anInterface = (ParameterizedType) genericInterface;
......
......@@ -89,6 +89,8 @@ public enum NodeType {
return MQ;
case 5:
return Cache;
case 6:
return Browser;
case 10:
return User;
case 11:
......
/*
* 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.analysis.metrics;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Entrance;
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Expression;
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.MetricsFunction;
import org.apache.skywalking.oap.server.core.query.sql.Function;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
@MetricsFunction(functionName = "rate")
public abstract class RateMetrics extends Metrics implements IntValueHolder {
protected static final String DENOMINATOR = "denominator";
protected static final String NUMERATOR = "numerator";
protected static final String PERCENTAGE = "percentage";
@Getter
@Setter
@Column(columnName = DENOMINATOR)
private long denominator;
@Getter
@Setter
@Column(columnName = PERCENTAGE, dataType = Column.ValueDataType.COMMON_VALUE, function = Function.Avg)
private int percentage;
@Getter
@Setter
@Column(columnName = NUMERATOR)
private long numerator;
@Entrance
public final void combine(@Expression boolean isNumerator, @Expression boolean isDenominator) {
if (isNumerator) {
numerator++;
}
if (isDenominator) {
denominator++;
}
}
@Override
public final void combine(Metrics metrics) {
denominator += ((RateMetrics) metrics).denominator;
numerator += ((RateMetrics) metrics).numerator;
}
@Override
public void calculate() {
percentage = (int) (numerator * 10000 / denominator);
}
@Override
public int getValue() {
return percentage;
}
}
......@@ -22,7 +22,6 @@ import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.FilterM
@FilterMatcher
public class InMatch {
public boolean match(Object left, Object[] rights) {
for (Object right : rights) {
if (right instanceof String) {
......
/*
* 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.manual;
import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTrafficCategory;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTrafficSource;
public abstract class BrowserAppTrafficSourceDispatcher<SOURCE extends BrowserAppTrafficSource> implements SourceDispatcher<SOURCE> {
@Override
public void dispatch(final SOURCE source) {
// filter error traffic
if (!source.getTrafficCategory().equals(BrowserAppTrafficCategory.NORMAL)) {
return;
}
dispatchInterval(source);
}
protected abstract void dispatchInterval(SOURCE source);
}
/*
* 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.manual.endpoint;
import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
import org.apache.skywalking.oap.server.core.analysis.manual.endpoint.EndpointTraffic;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.browser.manual.BrowserAppTrafficSourceDispatcher;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppPageTraffic;
public class BrowserAppPageTrafficDispatcher extends BrowserAppTrafficSourceDispatcher<BrowserAppPageTraffic> implements SourceDispatcher<BrowserAppPageTraffic> {
@Override
protected void dispatchInterval(final BrowserAppPageTraffic source) {
EndpointTraffic traffic = new EndpointTraffic();
traffic.setTimeBucket(source.getTimeBucket());
traffic.setName(source.getName());
traffic.setServiceId(source.getServiceId());
MetricsStreamProcessor.getInstance().in(traffic);
}
}
/*
* 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.manual.errorlog;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.core.analysis.Stream;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
@Stream(name = BrowserErrorLogRecord.INDEX_NAME, scopeId = DefaultScopeDefine.BROWSER_ERROR_LOG, builder = BrowserErrorLogRecord.Builder.class, processor = RecordStreamProcessor.class)
public class BrowserErrorLogRecord extends Record {
public static final String INDEX_NAME = "browser_error_log";
public static final String UNIQUE_ID = "unique_id";
public static final String SERVICE_ID = "service_id";
public static final String SERVICE_VERSION_ID = "service_version_id";
public static final String PAGE_PATH_ID = "pate_path_id";
public static final String PAGE_PATH = "page_path";
public static final String TIMESTAMP = "timestamp";
public static final String ERROR_CATEGORY = "error_category";
public static final String DATA_BINARY = "data_binary";
@Override
public String id() {
return uniqueId;
}
@Setter
@Getter
@Column(columnName = UNIQUE_ID)
private String uniqueId;
@Setter
@Getter
@Column(columnName = SERVICE_ID)
private String serviceId;
@Setter
@Getter
@Column(columnName = SERVICE_VERSION_ID)
private String serviceVersionId;
@Setter
@Getter
@Column(columnName = PAGE_PATH_ID)
private String pagePathId;
@Setter
@Getter
@Column(columnName = PAGE_PATH, matchQuery = true)
private String pagePath;
@Setter
@Getter
@Column(columnName = TIMESTAMP)
private long timestamp;
@Setter
@Getter
@Column(columnName = ERROR_CATEGORY)
private int errorCategory;
@Setter
@Getter
@Column(columnName = DATA_BINARY)
private byte[] dataBinary;
public static class Builder implements StorageBuilder<BrowserErrorLogRecord> {
@Override
public BrowserErrorLogRecord map2Data(final Map<String, Object> dbMap) {
BrowserErrorLogRecord record = new BrowserErrorLogRecord();
record.setUniqueId((String) dbMap.get(UNIQUE_ID));
record.setServiceId((String) dbMap.get(SERVICE_ID));
record.setServiceVersionId((String) dbMap.get(SERVICE_VERSION_ID));
record.setPagePathId((String) dbMap.get(PAGE_PATH_ID));
record.setPagePath((String) dbMap.get(PAGE_PATH));
record.setTimestamp(((Number) dbMap.get(TIMESTAMP)).longValue());
record.setTimeBucket(((Number) dbMap.get(TIME_BUCKET)).longValue());
record.setErrorCategory(((Number) dbMap.get(ERROR_CATEGORY)).intValue());
String dataBinary = (String) dbMap.get(DATA_BINARY);
if (StringUtil.isEmpty(dataBinary)) {
record.setDataBinary(new byte[] {});
} else {
record.setDataBinary(Base64.getDecoder().decode(dataBinary));
}
return record;
}
@Override
public Map<String, Object> data2Map(final BrowserErrorLogRecord storageData) {
Map<String, Object> map = new HashMap<>();
map.put(UNIQUE_ID, storageData.getUniqueId());
map.put(SERVICE_ID, storageData.getServiceId());
map.put(SERVICE_VERSION_ID, storageData.getServiceVersionId());
map.put(PAGE_PATH_ID, storageData.getPagePathId());
map.put(PAGE_PATH, storageData.getPagePath());
map.put(TIMESTAMP, storageData.getTimestamp());
map.put(TIME_BUCKET, storageData.getTimeBucket());
map.put(ERROR_CATEGORY, storageData.getErrorCategory());
if (CollectionUtils.isEmpty(storageData.getDataBinary())) {
map.put(DATA_BINARY, Const.EMPTY_STRING);
} else {
map.put(DATA_BINARY, new String(Base64.getEncoder().encode(storageData.getDataBinary())));
}
return map;
}
}
}
/*
* 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.manual.errorlog;
import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorLog;
public class BrowserErrorLogRecordDispatcher implements SourceDispatcher<BrowserErrorLog> {
@Override
public void dispatch(final BrowserErrorLog source) {
BrowserErrorLogRecord record = new BrowserErrorLogRecord();
record.setUniqueId(source.getUniqueId());
record.setServiceId(source.getServiceId());
record.setServiceVersionId(source.getServiceVersionId());
record.setPagePathId(source.getPagePathId());
record.setPagePath(source.getPagePath());
record.setTimestamp(source.getTimestamp());
record.setTimeBucket(source.getTimeBucket());
record.setErrorCategory(source.getErrorCategory().getValue());
record.setDataBinary(source.getDataBinary());
RecordStreamProcessor.getInstance().in(record);
}
}
/*
* 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.manual.instance;
import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.browser.manual.BrowserAppTrafficSourceDispatcher;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppSingleVersionTraffic;
public class BrowserAppSingleVersionTrafficDispatcher extends BrowserAppTrafficSourceDispatcher<BrowserAppSingleVersionTraffic> implements SourceDispatcher<BrowserAppSingleVersionTraffic> {
@Override
protected void dispatchInterval(final BrowserAppSingleVersionTraffic source) {
InstanceTraffic traffic = new InstanceTraffic();
traffic.setTimeBucket(source.getTimeBucket());
traffic.setName(source.getName());
traffic.setServiceId(source.getServiceId());
traffic.setLastPingTimestamp(source.getTimeBucket());
MetricsStreamProcessor.getInstance().in(traffic);
}
}
/*
* 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.manual.service;
import org.apache.skywalking.oap.server.core.analysis.SourceDispatcher;
import org.apache.skywalking.oap.server.core.analysis.manual.service.ServiceTraffic;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.browser.manual.BrowserAppTrafficSourceDispatcher;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTraffic;
public class BrowserAppTrafficDispatcher extends BrowserAppTrafficSourceDispatcher<BrowserAppTraffic> implements SourceDispatcher<BrowserAppTraffic> {
@Override
protected void dispatchInterval(final BrowserAppTraffic source) {
ServiceTraffic traffic = new ServiceTraffic();
traffic.setTimeBucket(source.getTimeBucket());
traffic.setName(source.getName());
traffic.setNodeType(source.getNodeType());
MetricsStreamProcessor.getInstance().in(traffic);
}
}
/*
* 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 static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_PAGE_PERF;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.ENDPOINT_CATALOG_NAME;
@ScopeDeclaration(id = BROWSER_APP_PAGE_PERF, name = "BrowserAppPagePerf", catalog = ENDPOINT_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class)
public class BrowserAppPagePerf extends BrowserAppPerfSource {
@Override
public int scope() {
return BROWSER_APP_PAGE_PERF;
}
@Override
public String getEntityId() {
return IDManager.EndpointID.buildId(serviceId, name);
}
@Getter
@ScopeDefaultColumn.DefinedByField(columnName = "service_id")
private String serviceId;
@Getter
@Setter
@ScopeDefaultColumn.DefinedByField(columnName = "service_name", requireDynamicActive = true)
private String serviceName;
@Override
public void prepare() {
serviceId = IDManager.ServiceID.buildId(serviceName, nodeType);
}
}
/*
* 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 static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_PAGE_TRAFFIC;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.ENDPOINT_CATALOG_NAME;
@ScopeDeclaration(id = BROWSER_APP_PAGE_TRAFFIC, name = "BrowserAppPageTraffic", catalog = ENDPOINT_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class)
public class BrowserAppPageTraffic extends BrowserAppTrafficSource {
@Override
public int scope() {
return BROWSER_APP_PAGE_TRAFFIC;
}
@Override
public String getEntityId() {
return IDManager.EndpointID.buildId(serviceId, name);
}
@Getter
@ScopeDefaultColumn.DefinedByField(columnName = "service_id")
private String serviceId;
@Getter
@Setter
@ScopeDefaultColumn.DefinedByField(columnName = "service_name", requireDynamicActive = true)
private String serviceName;
@Override
public void prepare() {
serviceId = IDManager.ServiceID.buildId(serviceName, nodeType);
}
}
/*
* 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 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 static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_PERF;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SERVICE_CATALOG_NAME;
@ScopeDeclaration(id = BROWSER_APP_PERF, name = "BrowserAppPerf", catalog = SERVICE_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class)
public class BrowserAppPerf extends BrowserAppPerfSource {
@Override
public int scope() {
return BROWSER_APP_PERF;
}
@Override
public String getEntityId() {
return IDManager.ServiceID.buildId(name, nodeType);
}
}
/*
* 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.NodeType;
import org.apache.skywalking.oap.server.core.source.Source;
/**
* Browser performance details
*/
@Setter
@Getter
public abstract class BrowserAppPerfSource extends Source {
protected String name;
protected final NodeType nodeType = NodeType.Browser;
private int redirectTime;
private int dnsTime;
private int ttfbTime;
private int tcpTime;
private int transTime;
private int domAnalysisTime;
private int fptTime;
private int domReadyTime;
private int loadPageTime;
private int resTime;
private int sslTime;
private int ttlTime;
private int firstPackTime;
private int fmpTime;
}
/*
* 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 static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_SINGLE_VERSION_PERF;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SERVICE_INSTANCE_CATALOG_NAME;
@ScopeDeclaration(id = BROWSER_APP_SINGLE_VERSION_PERF, name = "BrowserAppSingleVersionPerf", catalog = SERVICE_INSTANCE_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class)
public class BrowserAppSingleVersionPerf extends BrowserAppPerfSource {
@Override
public int scope() {
return BROWSER_APP_SINGLE_VERSION_PERF;
}
@Override
public String getEntityId() {
return IDManager.ServiceInstanceID.buildId(serviceId, name);
}
@Getter
@ScopeDefaultColumn.DefinedByField(columnName = "service_id")
private String serviceId;
@Getter
@Setter
@ScopeDefaultColumn.DefinedByField(columnName = "service_name", requireDynamicActive = true)
private String serviceName;
@Override
public void prepare() {
serviceId = IDManager.ServiceID.buildId(serviceName, nodeType);
}
}
/*
* 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 static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_SINGLE_VERSION_TRAFFIC;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SERVICE_INSTANCE_CATALOG_NAME;
@ScopeDeclaration(id = BROWSER_APP_SINGLE_VERSION_TRAFFIC, name = "BrowserAppSingleVersionTraffic", catalog = SERVICE_INSTANCE_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class)
public class BrowserAppSingleVersionTraffic extends BrowserAppTrafficSource {
@Override
public int scope() {
return BROWSER_APP_SINGLE_VERSION_TRAFFIC;
}
@Override
public String getEntityId() {
return IDManager.ServiceInstanceID.buildId(serviceId, name);
}
@Getter
@ScopeDefaultColumn.DefinedByField(columnName = "service_id")
private String serviceId;
@Getter
@Setter
@ScopeDefaultColumn.DefinedByField(columnName = "service_name", requireDynamicActive = true)
private String serviceName;
@Override
public void prepare() {
serviceId = IDManager.ServiceID.buildId(serviceName, nodeType);
}
}
/*
* 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 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 static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_APP_TRAFFIC;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SERVICE_CATALOG_NAME;
@ScopeDeclaration(id = BROWSER_APP_TRAFFIC, name = "BrowserAppTraffic", catalog = SERVICE_CATALOG_NAME)
@ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName = "entity_id", isID = true, type = String.class)
public class BrowserAppTraffic extends BrowserAppTrafficSource {
@Override
public int scope() {
return BROWSER_APP_TRAFFIC;
}
@Override
public String getEntityId() {
return IDManager.ServiceID.buildId(name, nodeType);
}
}
/*
* 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;
public enum BrowserAppTrafficCategory {
/**
* From the BrowserPerfData.
*/
NORMAL,
/**
* From the BrowserErrorLog and BrowserErrorLog#firstReportedError = true.
*/
FIRST_ERROR,
/**
* From the BrowserErrorLog and BrowserErrorLog#firstReportedError = false.
*/
ERROR
}
/*
* 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.NodeType;
import org.apache.skywalking.oap.server.core.source.ScopeDefaultColumn;
import org.apache.skywalking.oap.server.core.source.Source;
/**
* From js client reported access traffic
*/
@Setter
@Getter
public abstract class BrowserAppTrafficSource extends Source {
@ScopeDefaultColumn.DefinedByField(columnName = "name", requireDynamicActive = true)
protected String name;
protected final NodeType nodeType = NodeType.Browser;
private final int count = 1;
private BrowserAppTrafficCategory trafficCategory;
/**
* if {@link #trafficCategory} is {@link BrowserAppTrafficCategory#NORMAL}, errorCategory is null.
*/
private BrowserErrorCategory errorCategory;
}
/*
* 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 org.apache.skywalking.apm.network.language.agent.v3.ErrorCategory;
public enum BrowserErrorCategory {
AJAX(0), RESOURCE(1), VUE(2), PROMISE(3), JS(4), UNKNOWN(5);
public static BrowserErrorCategory fromErrorCategory(ErrorCategory category) {
switch (category) {
case ajax:
return BrowserErrorCategory.AJAX;
case resource:
return BrowserErrorCategory.RESOURCE;
case vue:
return BrowserErrorCategory.VUE;
case promise:
return BrowserErrorCategory.PROMISE;
case js:
return BrowserErrorCategory.JS;
default:
return BrowserErrorCategory.UNKNOWN;
}
}
@Getter
private final int value;
BrowserErrorCategory(int value) {
this.value = value;
}
}
/*
* 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.source.ScopeDeclaration;
import org.apache.skywalking.oap.server.core.source.Source;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.BROWSER_ERROR_LOG;
/**
* Browser error log raw data
*/
@ScopeDeclaration(id = BROWSER_ERROR_LOG, name = "BrowserErrorLog")
public class BrowserErrorLog extends Source {
@Override
public int scope() {
return BROWSER_ERROR_LOG;
}
@Override
public String getEntityId() {
return uniqueId;
}
@Getter
@Setter
private String uniqueId;
@Getter
@Setter
private String serviceId;
@Getter
@Setter
private String serviceVersionId;
@Getter
@Setter
private String pagePathId;
@Getter
@Setter
private String pagePath;
@Getter
@Setter
private long timestamp;
@Getter
@Setter
private BrowserErrorCategory errorCategory;
@Getter
@Setter
private byte[] dataBinary;
}
/*
* 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.query;
import java.io.IOException;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.core.query.type.ErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.Pagination;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.module.Service;
@RequiredArgsConstructor
public class BrowserLogQueryService implements Service {
private final ModuleManager moduleManager;
private IBrowserLogQueryDAO browserLogQueryDAO;
private IBrowserLogQueryDAO getBrowserLogQueryDAO() {
return Optional.ofNullable(browserLogQueryDAO).orElseGet(() -> {
browserLogQueryDAO = moduleManager.find(StorageModule.NAME)
.provider()
.getService(IBrowserLogQueryDAO.class);
return browserLogQueryDAO;
});
}
public BrowserErrorLogs queryBrowserErrorLogs(final String serviceId,
final String serviceVersionId,
final String pagePathId,
final String pagePath,
final ErrorCategory category,
final long startSecondTB,
final long endSecondTB,
final Pagination paging) throws IOException {
PaginationUtils.Page page = PaginationUtils.INSTANCE.exchange(paging);
BrowserErrorCategory errorCategory = Optional.ofNullable(category)
.map(c -> BrowserErrorCategory.valueOf(c.name()))
.orElse(null);
return getBrowserLogQueryDAO().queryBrowserErrorLogs(
serviceId, serviceVersionId, pagePathId, pagePath, errorCategory, startSecondTB, endSecondTB,
page.getLimit(),
page.getFrom()
);
}
}
/*
* 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.query.input;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.query.type.ErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.Pagination;
@Setter
@Getter
public class BrowserErrorLogQueryCondition {
private String serviceId;
private String serviceVersionId;
private String pagePathId;
private String pagePath;
private ErrorCategory category;
private Duration queryDuration;
private Pagination paging;
}
/*
* 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.query.type;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class BrowserErrorLog {
private String service;
private String serviceVersion;
private Long time;
private String pagePath;
private ErrorCategory category;
private String grade;
private String message;
private Integer line;
private Integer col;
private String stack;
private String errorUrl;
private boolean firstReportedError;
}
/*
* 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.query.type;
import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
@Getter
public class BrowserErrorLogs {
private final List<BrowserErrorLog> logs;
@Setter
private int total;
public BrowserErrorLogs() {
this.logs = new ArrayList<>();
}
}
/*
* 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.query.type;
public enum ErrorCategory {
ALL,
AJAX,
RESOURCE,
VUE,
PROMISE,
JS,
UNKNOWN
}
......@@ -69,6 +69,15 @@ public class DefaultScopeDefine {
public static final int UI_TEMPLATE = 32;
public static final int SERVICE_INSTANCE_JVM_THREAD = 33;
// browser
public static final int BROWSER_ERROR_LOG = 34;
public static final int BROWSER_APP_PERF = 35;
public static final int BROWSER_APP_PAGE_PERF = 36;
public static final int BROWSER_APP_SINGLE_VERSION_PERF = 37;
public static final int BROWSER_APP_TRAFFIC = 38;
public static final int BROWSER_APP_SINGLE_VERSION_TRAFFIC = 39;
public static final int BROWSER_APP_PAGE_TRAFFIC = 40;
/**
* Catalog of scope, the metrics processor could use this to group all generated metrics by oal rt.
*/
......
......@@ -25,6 +25,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDA
import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -63,7 +64,8 @@ public class StorageModule extends ModuleDefine {
IProfileTaskQueryDAO.class,
IProfileTaskLogQueryDAO.class,
IProfileThreadSnapshotQueryDAO.class,
UITemplateManagementDAO.class
UITemplateManagementDAO.class,
IBrowserLogQueryDAO.class
};
}
}
/*
* 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.storage.query;
import com.google.protobuf.InvalidProtocolBufferException;
import java.io.IOException;
import java.util.Base64;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLog;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.core.query.type.ErrorCategory;
import org.apache.skywalking.oap.server.library.module.Service;
public interface IBrowserLogQueryDAO extends Service {
BrowserErrorLogs queryBrowserErrorLogs(String serviceId,
String serviceVersionId,
String pagePathId,
String pagePath,
BrowserErrorCategory category,
long startSecondTB,
long endSecondTB,
int limit,
int from) throws IOException;
/**
* Parser the raw error log.
*/
default BrowserErrorLog parserDataBinary(
String dataBinaryBase64) {
try {
BrowserErrorLog log = new BrowserErrorLog();
org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog browserErrorLog = org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog
.parseFrom(Base64.getDecoder().decode(dataBinaryBase64));
log.setService(browserErrorLog.getService());
log.setServiceVersion(browserErrorLog.getServiceVersion());
log.setTime(browserErrorLog.getTime());
log.setPagePath(browserErrorLog.getPagePath());
log.setCategory(ErrorCategory.valueOf(browserErrorLog.getCategory().name().toUpperCase()));
log.setGrade(browserErrorLog.getGrade());
log.setMessage(browserErrorLog.getMessage());
log.setLine(browserErrorLog.getLine());
log.setCol(browserErrorLog.getCol());
log.setStack(browserErrorLog.getStack());
log.setErrorUrl(browserErrorLog.getErrorUrl());
log.setFirstReportedError(browserErrorLog.getFirstReportedError());
return log;
} catch (InvalidProtocolBufferException e) {
throw new RuntimeException(e);
}
}
}
......@@ -26,6 +26,6 @@ public class CoreModuleTest {
public void testOpenServiceList() {
CoreModule coreModule = new CoreModule();
Assert.assertEquals(31, coreModule.services().length);
Assert.assertEquals(32, coreModule.services().length);
}
}
......@@ -23,6 +23,7 @@ import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import org.apache.skywalking.oap.query.graphql.resolver.AggregationQuery;
import org.apache.skywalking.oap.query.graphql.resolver.AlarmQuery;
import org.apache.skywalking.oap.query.graphql.resolver.BrowserLogQuery;
import org.apache.skywalking.oap.query.graphql.resolver.HealthQuery;
import org.apache.skywalking.oap.query.graphql.resolver.LogQuery;
import org.apache.skywalking.oap.query.graphql.resolver.MetadataQuery;
......@@ -72,48 +73,50 @@ public class GraphQLQueryProvider extends ModuleProvider {
@Override
public void prepare() throws ServiceNotProvidedException, ModuleStartException {
GraphQLSchema schema = SchemaParser.newParser()
.file("query-protocol/common.graphqls")
.resolvers(new Query(), new Mutation(), new HealthQuery(getManager()))
.file("query-protocol/metadata.graphqls")
.resolvers(new MetadataQuery(getManager()))
.file("query-protocol/topology.graphqls")
.resolvers(new TopologyQuery(getManager()))
/**
* Metrics v2 query protocol is an alternative metrics query(s) of original v1,
* defined in the metric.graphql, top-n-records.graphqls, and aggregation.graphqls.
*/
.file("query-protocol/metrics-v2.graphqls")
.resolvers(new MetricsQuery(getManager()))
////////
//Deprecated Queries
////////
.file("query-protocol/metric.graphqls")
.resolvers(new MetricQuery(getManager()))
.file("query-protocol/aggregation.graphqls")
.resolvers(new AggregationQuery(getManager()))
.file("query-protocol/top-n-records.graphqls")
.resolvers(new TopNRecordsQuery(getManager()))
////////
.file("query-protocol/trace.graphqls")
.resolvers(new TraceQuery(getManager()))
.file("query-protocol/alarm.graphqls")
.resolvers(new AlarmQuery(getManager()))
.file("query-protocol/log.graphqls")
.resolvers(new LogQuery(getManager()))
.file("query-protocol/profile.graphqls")
.resolvers(new ProfileQuery(getManager()), new ProfileMutation(getManager()))
.file("query-protocol/ui-configuration.graphqls")
.resolvers(new UIConfigurationManagement(getManager()))
.build()
.makeExecutableSchema();
.file("query-protocol/common.graphqls")
.resolvers(new Query(), new Mutation(), new HealthQuery(getManager()))
.file("query-protocol/metadata.graphqls")
.resolvers(new MetadataQuery(getManager()))
.file("query-protocol/topology.graphqls")
.resolvers(new TopologyQuery(getManager()))
/**
* Metrics v2 query protocol is an alternative metrics query(s) of original v1,
* defined in the metric.graphql, top-n-records.graphqls, and aggregation.graphqls.
*/
.file("query-protocol/metrics-v2.graphqls")
.resolvers(new MetricsQuery(getManager()))
////////
//Deprecated Queries
////////
.file("query-protocol/metric.graphqls")
.resolvers(new MetricQuery(getManager()))
.file("query-protocol/aggregation.graphqls")
.resolvers(new AggregationQuery(getManager()))
.file("query-protocol/top-n-records.graphqls")
.resolvers(new TopNRecordsQuery(getManager()))
////////
.file("query-protocol/trace.graphqls")
.resolvers(new TraceQuery(getManager()))
.file("query-protocol/alarm.graphqls")
.resolvers(new AlarmQuery(getManager()))
.file("query-protocol/log.graphqls")
.resolvers(new LogQuery(getManager()))
.file("query-protocol/profile.graphqls")
.resolvers(new ProfileQuery(getManager()), new ProfileMutation(getManager()))
.file("query-protocol/ui-configuration.graphqls")
.resolvers(new UIConfigurationManagement(getManager()))
.file("query-protocol/browser-log.graphqls")
.resolvers(new BrowserLogQuery(getManager()))
.build()
.makeExecutableSchema();
this.graphQL = GraphQL.newGraphQL(schema).build();
}
@Override
public void start() throws ServiceNotProvidedException, ModuleStartException {
JettyHandlerRegister service = getManager().find(CoreModule.NAME)
.provider()
.getService(JettyHandlerRegister.class);
.provider()
.getService(JettyHandlerRegister.class);
service.addHandler(new GraphQLQueryHandler(config.getPath(), graphQL));
}
......
/*
* 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.query.graphql.resolver;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import java.io.IOException;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.query.BrowserLogQueryService;
import org.apache.skywalking.oap.server.core.query.input.BrowserErrorLogQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import static java.util.Objects.nonNull;
@RequiredArgsConstructor
public class BrowserLogQuery implements GraphQLQueryResolver {
private final ModuleManager moduleManager;
private BrowserLogQueryService queryService;
private BrowserLogQueryService getQueryService() {
return Optional.ofNullable(queryService).orElseGet(() -> {
queryService = moduleManager.find(CoreModule.NAME).provider().getService(BrowserLogQueryService.class);
return queryService;
});
}
public BrowserErrorLogs queryBrowserErrorLogs(BrowserErrorLogQueryCondition condition) throws IOException {
long startSecondTB = 0, endSecondTB = 0;
if (nonNull(condition.getQueryDuration())) {
startSecondTB = condition.getQueryDuration()
.getStartTimeBucketInSec();
endSecondTB = condition.getQueryDuration()
.getEndTimeBucketInSec();
}
return getQueryService().queryBrowserErrorLogs(
condition.getServiceId(), condition.getServiceVersionId(), condition.getPagePathId(),
condition.getPagePath(), condition.getCategory()
, startSecondTB, endSecondTB, condition.getPaging()
);
}
}
Subproject commit 5ecefdf2c16ca16d4973806bdd26f9eafa3faf1d
Subproject commit 92f62f13be3a2bf3dfd007ee85c68d54af2c6149
......@@ -42,6 +42,7 @@
<module>skywalking-profile-receiver-plugin</module>
<module>opencensus-receiver-plugin</module>
<module>skywalking-meter-receiver-plugin</module>
<module>skywalking-browser-receiver-plugin</module>
</modules>
<dependencies>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>server-receiver-plugin</artifactId>
<groupId>org.apache.skywalking</groupId>
<version>8.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>skywalking-browser-receiver-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>skywalking-sharing-server-plugin</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
/*
* 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.module;
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
public class BrowserModule extends ModuleDefine {
private static final String NAME = "receiver-browser";
public BrowserModule() {
super(NAME);
}
@Override
public Class[] services() {
return new Class[0];
}
}
/*
* 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;
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.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.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;
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.sharing.server.SharingServerModule;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
public class BrowserModuleProvider extends ModuleProvider {
private final BrowserServiceModuleConfig moduleConfig = new BrowserServiceModuleConfig();
@Override
public String name() {
return "default";
}
@Override
public Class<? extends ModuleDefine> module() {
return BrowserModule.class;
}
@Override
public ModuleConfig createConfigBeanIfAbsent() {
return moduleConfig;
}
@Override
public void prepare() throws ServiceNotProvidedException, ModuleStartException {
}
@Override
public void start() throws ServiceNotProvidedException, ModuleStartException {
// load browser analysis
getManager().find(CoreModule.NAME)
.provider()
.getService(OALEngineLoaderService.class)
.load(BrowserOALDefine.INSTANCE);
GRPCHandlerRegister grpcHandlerRegister = getManager().find(SharingServerModule.NAME)
.provider().getService(GRPCHandlerRegister.class);
grpcHandlerRegister.addHandler(
new BrowserPerfServiceHandler(
getManager(), moduleConfig, perfDataListenerManager(), errorLogListenerManager()));
}
@Override
public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException {
}
@Override
public String[] requiredModules() {
return new String[] {
TelemetryModule.NAME,
CoreModule.NAME,
SharingServerModule.NAME,
ConfigurationModule.NAME
};
}
private PerfDataParserListenerManager perfDataListenerManager() {
PerfDataParserListenerManager listenerManager = new PerfDataParserListenerManager();
listenerManager.add(new MultiScopesPerfDataAnalysisListener.Factory(getManager(), moduleConfig));
return listenerManager;
}
private ErrorLogParserListenerManager errorLogListenerManager() {
ErrorLogParserListenerManager listenerManager = new ErrorLogParserListenerManager();
listenerManager.add(new MultiScopesErrorLogAnalysisListener.Factory(getManager(), moduleConfig));
listenerManager.add(new ErrorLogRecordListener.Factory(getManager(), moduleConfig));
return listenerManager;
}
}
/*
* 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;
import org.apache.skywalking.oap.server.core.oal.rt.OALDefine;
/**
* Browser OAL script includes the metrics related to browser only.
*/
public class BrowserOALDefine extends OALDefine {
public static final BrowserOALDefine INSTANCE = new BrowserOALDefine();
private BrowserOALDefine() {
super(
"oal/browser.oal",
"org.apache.skywalking.oap.server.core.browser.source"
);
}
}
/*
* 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;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.oap.server.library.module.ModuleConfig;
public class BrowserServiceModuleConfig extends ModuleConfig {
/**
* The sample rate precision is 1/10000. 10000 means 100% sample in default.
*/
@Setter
@Getter
private int sampleRate = 10000;
}
/*
* 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;
import io.grpc.stub.StreamObserver;
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.BrowserPerfServiceGrpc;
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.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;
/**
* Collect and process the performance and error log.
*/
@Slf4j
public class BrowserPerfServiceHandler extends BrowserPerfServiceGrpc.BrowserPerfServiceImplBase implements GRPCHandler {
private final ModuleManager moduleManager;
private final BrowserServiceModuleConfig config;
private final PerfDataParserListenerManager perfDataListenerManager;
private final ErrorLogParserListenerManager errorLogListenerManager;
// performance
private final HistogramMetrics perfHistogram;
private final CounterMetrics perfErrorCounter;
// error log
private final HistogramMetrics errorLogHistogram;
private final CounterMetrics logErrorCounter;
public BrowserPerfServiceHandler(ModuleManager moduleManager,
BrowserServiceModuleConfig config,
PerfDataParserListenerManager perfDataListenerManager,
ErrorLogParserListenerManager errorLogListenerManager) {
this.moduleManager = moduleManager;
this.config = config;
this.perfDataListenerManager = perfDataListenerManager;
this.errorLogListenerManager = errorLogListenerManager;
MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME)
.provider()
.getService(MetricsCreator.class);
// performance
perfHistogram = metricsCreator.createHistogramMetric(
"browser_perf_data_in_latency", "The process latency of browser performance data",
new MetricsTag.Keys("protocol"), new MetricsTag.Values("grpc")
);
perfErrorCounter = metricsCreator.createCounter(
"browser_perf_data_analysis_error_count", "The error number of browser performance data analysis",
new MetricsTag.Keys("protocol"), new MetricsTag.Values("grpc")
);
// error log
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("grpc")
);
}
@Override
public void collectPerfData(final BrowserPerfData request, final StreamObserver<Commands> responseObserver) {
if (log.isDebugEnabled()) {
log.debug("receive browser performance data");
}
HistogramMetrics.Timer timer = perfHistogram.createTimer();
try {
PerfDataAnalyzer analyzer = new PerfDataAnalyzer(moduleManager, perfDataListenerManager, config);
analyzer.doAnalysis(request);
} catch (Throwable e) {
log.error(e.getMessage(), e);
perfErrorCounter.inc();
} finally {
timer.finish();
responseObserver.onNext(Commands.newBuilder().build());
responseObserver.onCompleted();
}
}
@Override
public StreamObserver<BrowserErrorLog> collectErrorLogs(final StreamObserver<Commands> responseObserver) {
return new StreamObserver<BrowserErrorLog>() {
@Override
public void onNext(final BrowserErrorLog browserErrorLog) {
if (log.isDebugEnabled()) {
log.debug("receive browser error log");
}
HistogramMetrics.Timer timer = errorLogHistogram.createTimer();
try {
ErrorLogAnalyzer analyzer = new ErrorLogAnalyzer(moduleManager, errorLogListenerManager, config);
analyzer.doAnalysis(browserErrorLog);
} catch (Throwable e) {
log.error(e.getMessage(), e);
logErrorCounter.inc();
} finally {
timer.finish();
}
}
@Override
public void onError(final Throwable throwable) {
log.error(throwable.getMessage(), throwable);
responseObserver.onCompleted();
}
@Override
public void onCompleted() {
responseObserver.onNext(Commands.newBuilder().build());
responseObserver.onCompleted();
}
};
}
}
/*
* 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.errorlog;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog;
import org.apache.skywalking.apm.network.language.agent.v3.ErrorCategory;
@RequiredArgsConstructor
public class BrowserErrorLogDecorator {
private boolean isOrigin = true;
private final BrowserErrorLog errorLog;
private BrowserErrorLog.Builder builder;
public String getUniqueId() {
return isOrigin ? errorLog.getUniqueId() : builder.getUniqueId();
}
public String getService() {
return isOrigin ? errorLog.getService() : builder.getService();
}
public String getServiceVersion() {
return isOrigin ? errorLog.getServiceVersion() : builder.getServiceVersion();
}
public long getTime() {
return isOrigin ? errorLog.getTime() : builder.getTime();
}
public String getPagePath() {
return isOrigin ? errorLog.getPagePath() : builder.getPagePath();
}
public ErrorCategory getCategory() {
return isOrigin ? errorLog.getCategory() : builder.getCategory();
}
public String getGrade() {
return isOrigin ? errorLog.getGrade() : builder.getGrade();
}
public String getMessage() {
return isOrigin ? errorLog.getMessage() : builder.getMessage();
}
public int getLine() {
return isOrigin ? errorLog.getLine() : builder.getLine();
}
public int getCol() {
return isOrigin ? errorLog.getCol() : builder.getCol();
}
public String getStack() {
return isOrigin ? errorLog.getStack() : builder.getStack();
}
public String getErrorUrl() {
return isOrigin ? errorLog.getErrorUrl() : builder.getErrorUrl();
}
public boolean isFirstReportedError() {
return isOrigin ? errorLog.getFirstReportedError() : builder.getFirstReportedError();
}
public byte[] toByteArray() {
return isOrigin ? errorLog.toByteArray() : builder.build().toByteArray();
}
public void setTime(long time) {
if (isOrigin) {
toBuilder();
}
builder.setTime(time);
}
void toBuilder() {
if (isOrigin) {
this.isOrigin = false;
this.builder = errorLog.toBuilder();
}
}
}
/*
* 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.errorlog;
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.BrowserErrorLog;
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.listener.ErrorLogAnalysisListener;
@Slf4j
@RequiredArgsConstructor
public class ErrorLogAnalyzer {
private final ModuleManager moduleManager;
private final ErrorLogParserListenerManager listenerManager;
private final BrowserServiceModuleConfig moduleConfig;
private final List<ErrorLogAnalysisListener> analysisListeners = new LinkedList<>();
public void doAnalysis(BrowserErrorLog errorLog) {
createAnalysisListeners();
try {
BrowserErrorLogDecorator decorator = new BrowserErrorLogDecorator(errorLog);
// Use the server side current time.
long nowMillis = System.currentTimeMillis();
decorator.setTime(nowMillis);
notifyListener(decorator);
notifyListenerToBuild();
} catch (Throwable e) {
log.error(e.getMessage(), e);
}
}
private void notifyListener(BrowserErrorLogDecorator decorator) {
analysisListeners.forEach(listener -> listener.parse(decorator));
}
private void notifyListenerToBuild() {
analysisListeners.forEach(ErrorLogAnalysisListener::build);
}
private void createAnalysisListeners() {
listenerManager.getErrorLogAnalysisListeners()
.forEach(factory -> analysisListeners.add(factory.create(moduleManager, moduleConfig)));
}
}
/*
* 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.errorlog;
import java.util.LinkedList;
import java.util.List;
import lombok.Getter;
import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.listener.ErrorLogListenerFactory;
public class ErrorLogParserListenerManager {
@Getter
private final List<ErrorLogListenerFactory> errorLogAnalysisListeners = new LinkedList<>();
public void add(final ErrorLogListenerFactory factory) {
errorLogAnalysisListeners.add(factory);
}
}
/*
* 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.errorlog.listener;
import org.apache.skywalking.oap.server.receiver.browser.provider.parser.errorlog.BrowserErrorLogDecorator;
/**
* ErrorLogAnalysisListener represents the callback when OAP does the browser error log analysis.
*/
public interface ErrorLogAnalysisListener {
/**
* The last step of the analysis process. Typically, the implementations forward the analysis results to the source
* receiver.
*/
void build();
/**
* Parse the raw data from the probe (js-client).
*/
void parse(BrowserErrorLogDecorator decorator);
}
/*
* 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.errorlog.listener;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig;
public interface ErrorLogListenerFactory {
ErrorLogAnalysisListener create(final ModuleManager moduleManager, final BrowserServiceModuleConfig moduleConfig);
}
/*
* 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.errorlog.listener;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.NodeType;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorLog;
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.errorlog.BrowserErrorLogDecorator;
/**
* ErrorLogRecordListener forwards the error log raw data to the persistence layer with the query required conditions.
*/
@Slf4j
@RequiredArgsConstructor
public class ErrorLogRecordListener implements ErrorLogAnalysisListener {
private final NamingControl namingControl;
private final SourceReceiver sourceReceiver;
private final BrowserErrorLog errorLog = new BrowserErrorLog();
private final ErrorLogRecordSampler sampler;
private SampleStatus sampleStatus = SampleStatus.UNKNOWN;
/**
* Send BrowserErrorLog to the oreceiver.
*/
@Override
public void build() {
if (sampleStatus.equals(SampleStatus.SAMPLED)) {
sourceReceiver.receive(errorLog);
}
}
@Override
public void parse(final BrowserErrorLogDecorator decorator) {
// sample
if (StringUtil.isEmpty(decorator.getUniqueId())) {
if (log.isDebugEnabled()) {
log.debug("Because uniqueId is empty BrowserErrorLog is ignored.");
}
sampleStatus = SampleStatus.IGNORED;
return;
}
if (!sampler.shouldSample(decorator.getUniqueId().hashCode())) {
sampleStatus = SampleStatus.IGNORED;
return;
}
sampleStatus = SampleStatus.SAMPLED;
// error log
errorLog.setUniqueId(decorator.getUniqueId());
errorLog.setTimeBucket(TimeBucket.getRecordTimeBucket(decorator.getTime()));
errorLog.setTimestamp(decorator.getTime());
// service
String serviceName = namingControl.formatServiceName(decorator.getService());
errorLog.setServiceId(IDManager.ServiceID.buildId(serviceName, NodeType.Browser));
// service version
String serviceVersionName = namingControl.formatInstanceName(decorator.getServiceVersion());
errorLog.setServiceVersionId(IDManager.ServiceInstanceID.buildId(serviceName, serviceVersionName));
// page
String pagePath = namingControl.formatEndpointName(serviceName, decorator.getPagePath());
errorLog.setPagePath(pagePath);
errorLog.setPagePathId(IDManager.EndpointID.buildId(serviceName, pagePath));
// raw data
errorLog.setErrorCategory(BrowserErrorCategory.fromErrorCategory(decorator.getCategory()));
errorLog.setDataBinary(decorator.toByteArray());
}
private enum SampleStatus {
UNKNOWN, SAMPLED, IGNORED
}
public static class Factory implements ErrorLogListenerFactory {
private final SourceReceiver sourceReceiver;
private final NamingControl namingControl;
private final ErrorLogRecordSampler sampler;
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);
this.sampler = new ErrorLogRecordSampler(moduleConfig.getSampleRate());
}
@Override
public ErrorLogAnalysisListener create(final ModuleManager moduleManager,
final BrowserServiceModuleConfig moduleConfig) {
return new ErrorLogRecordListener(namingControl, sourceReceiver, sampler);
}
}
}
/*
* 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.errorlog.listener;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.apm.network.language.agent.v3.BrowserErrorLog;
/**
* The sampler makes the sampling mechanism works at backend side. Sample result: [0,sampleRate) sampled, (sampleRate,~)
* ignored
*/
@RequiredArgsConstructor
public class ErrorLogRecordSampler {
private final int sampleRate;
/**
* through {@link BrowserErrorLog#getUniqueId()} hash code.
*/
public boolean shouldSample(int hashCode) {
return hashCode % 10000 < sampleRate;
}
}
/*
* 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.errorlog.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.BrowserAppTrafficCategory;
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.errorlog.BrowserErrorLogDecorator;
/**
* MultiScopesErrorLogAnalysisListener analysis error log, the kinds of error and error sum metrics.
*/
public class MultiScopesErrorLogAnalysisListener implements ErrorLogAnalysisListener {
private final SourceReceiver sourceReceiver;
private final SourceBuilder sourceBuilder;
public MultiScopesErrorLogAnalysisListener(final SourceReceiver sourceReceiver, final NamingControl namingControl) {
this.sourceReceiver = sourceReceiver;
this.sourceBuilder = new SourceBuilder(namingControl);
}
/**
* Send BrowserAppTraffic, BrowserAppSingleVersionTraffic, BrowserAppPageTraffic and BrowserAppPagePerf scope to the
* receiver.
*/
@Override
public void build() {
sourceReceiver.receive(sourceBuilder.toBrowserAppTraffic());
sourceReceiver.receive(sourceBuilder.toBrowserAppSingleVersionTraffic());
sourceReceiver.receive(sourceBuilder.toBrowserAppPageTraffic());
}
@Override
public void parse(final BrowserErrorLogDecorator decorator) {
sourceBuilder.setService(decorator.getService());
sourceBuilder.setServiceVersion(decorator.getServiceVersion());
sourceBuilder.setPatePath(decorator.getPagePath());
// time bucket
sourceBuilder.setTimeBucket(TimeBucket.getMinuteTimeBucket(decorator.getTime()));
// category
sourceBuilder.setTrafficCategory(
decorator.isFirstReportedError() ? BrowserAppTrafficCategory.FIRST_ERROR : BrowserAppTrafficCategory.ERROR);
sourceBuilder.setErrorCategory(decorator.getCategory());
}
public static class Factory implements ErrorLogListenerFactory {
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 ErrorLogAnalysisListener create(final ModuleManager moduleManager,
final BrowserServiceModuleConfig moduleConfig) {
return new MultiScopesErrorLogAnalysisListener(sourceReceiver, namingControl);
}
}
}
/*
* 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.errorlog.listener;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.skywalking.apm.network.language.agent.v3.ErrorCategory;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppPageTraffic;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppSingleVersionTraffic;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTraffic;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTrafficCategory;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTrafficSource;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.config.NamingControl;
@RequiredArgsConstructor
class SourceBuilder {
private final NamingControl namingControl;
@Getter
private String service;
public void setService(final String service) {
this.service = namingControl.formatServiceName(service);
}
@Getter
private String serviceVersion;
public void setServiceVersion(final String serviceVersion) {
this.serviceVersion = namingControl.formatInstanceName(serviceVersion);
}
@Getter
private String patePath;
public void setPatePath(final String patePath) {
this.patePath = namingControl.formatEndpointName(service, patePath);
}
@Setter
@Getter
private long timeBucket;
@Setter
@Getter
private BrowserAppTrafficCategory trafficCategory;
@Setter
@Getter
private BrowserErrorCategory errorCategory;
public void setErrorCategory(ErrorCategory category) {
this.errorCategory = BrowserErrorCategory.fromErrorCategory(category);
}
private void toBrowserAppTrafficSource(BrowserAppTrafficSource source) {
source.setTimeBucket(timeBucket);
source.setTrafficCategory(trafficCategory);
source.setErrorCategory(errorCategory);
}
/**
* Browser service traffic error related source.
*/
BrowserAppTraffic toBrowserAppTraffic() {
BrowserAppTraffic traffic = new BrowserAppTraffic();
toBrowserAppTrafficSource(traffic);
traffic.setName(service);
traffic.setTrafficCategory(trafficCategory);
traffic.setErrorCategory(errorCategory);
return traffic;
}
/**
* Browser single version error metrics related source.
*/
BrowserAppSingleVersionTraffic toBrowserAppSingleVersionTraffic() {
BrowserAppSingleVersionTraffic traffic = new BrowserAppSingleVersionTraffic();
toBrowserAppTrafficSource(traffic);
traffic.setName(serviceVersion);
traffic.setServiceName(service);
return traffic;
}
/**
* Browser page error metrics related source.
*/
BrowserAppPageTraffic toBrowserAppPageTraffic() {
BrowserAppPageTraffic traffic = new BrowserAppPageTraffic();
toBrowserAppTrafficSource(traffic);
traffic.setName(patePath);
traffic.setServiceName(service);
return traffic;
}
}
/*
* 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;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.apm.network.language.agent.v3.BrowserPerfData;
@RequiredArgsConstructor
public class BrowserPerfDataDecorator {
private boolean isOrigin = true;
private final BrowserPerfData browserPerfData;
private BrowserPerfData.Builder builder;
public String getService() {
return isOrigin ? browserPerfData.getService() : builder.getService();
}
public String getServiceVersion() {
return isOrigin ? browserPerfData.getServiceVersion() : builder.getServiceVersion();
}
public long getTime() {
return isOrigin ? browserPerfData.getTime() : builder.getTime();
}
public String getPagePath() {
return isOrigin ? browserPerfData.getPagePath() : builder.getPagePath();
}
public int getRedirectTime() {
return isOrigin ? browserPerfData.getRedirectTime() : builder.getRedirectTime();
}
public int getDnsTime() {
return isOrigin ? browserPerfData.getDnsTime() : builder.getDnsTime();
}
public int getTtfbTime() {
return isOrigin ? browserPerfData.getTtfbTime() : builder.getTtfbTime();
}
public int getTcpTime() {
return isOrigin ? browserPerfData.getTcpTime() : builder.getTcpTime();
}
public int getTransTime() {
return isOrigin ? browserPerfData.getTransTime() : builder.getTransTime();
}
public int getDomAnalysisTime() {
return isOrigin ? browserPerfData.getDomAnalysisTime() : builder.getDomAnalysisTime();
}
public int getFptTime() {
return isOrigin ? browserPerfData.getFptTime() : builder.getFptTime();
}
public int getDomReadyTime() {
return isOrigin ? browserPerfData.getDomReadyTime() : builder.getDomReadyTime();
}
public int getLoadPageTime() {
return isOrigin ? browserPerfData.getLoadPageTime() : builder.getLoadPageTime();
}
public int getResTime() {
return isOrigin ? browserPerfData.getResTime() : builder.getResTime();
}
public int getSslTime() {
return isOrigin ? browserPerfData.getSslTime() : builder.getSslTime();
}
public int getTtlTime() {
return isOrigin ? browserPerfData.getTtlTime() : builder.getTtlTime();
}
public int getFirstPackTime() {
return isOrigin ? browserPerfData.getFirstPackTime() : builder.getFirstPackTime();
}
public int getFmpTime() {
return isOrigin ? browserPerfData.getFmpTime() : builder.getFmpTime();
}
public void setTime(long time) {
if (isOrigin) {
toBuilder();
}
builder.setTime(time);
}
void toBuilder() {
if (isOrigin) {
this.isOrigin = false;
this.builder = browserPerfData.toBuilder();
}
}
}
/*
* 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;
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.receiver.browser.provider.BrowserServiceModuleConfig;
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 List<PerfDataAnalysisListener> analysisListeners = new LinkedList<>();
public void doAnalysis(BrowserPerfData browserPerfData) {
createAnalysisListeners();
try {
BrowserPerfDataDecorator decorator = new BrowserPerfDataDecorator(browserPerfData);
// Use the server side current time.
long nowMillis = System.currentTimeMillis();
decorator.setTime(nowMillis);
notifyListener(decorator);
notifyListenerToBuild();
} catch (Throwable e) {
log.error(e.getMessage(), e);
}
}
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)));
}
}
/*
* 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;
import java.util.LinkedList;
import java.util.List;
import lombok.Getter;
import org.apache.skywalking.oap.server.receiver.browser.provider.parser.performance.listener.PerfDataListenerFactory;
public class PerfDataParserListenerManager {
@Getter
private final List<PerfDataListenerFactory> perfDataListenerFactories = new LinkedList<>();
public void add(final PerfDataListenerFactory factory) {
perfDataListenerFactories.add(factory);
}
}
/*
* 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 lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.config.NamingControl;
import org.apache.skywalking.oap.server.core.source.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;
/**
* Browser traffic and page Performance related metrics.
*/
@Slf4j
public class MultiScopesPerfDataAnalysisListener implements PerfDataAnalysisListener {
private final SourceReceiver sourceReceiver;
private final SourceBuilder sourceBuilder;
public MultiScopesPerfDataAnalysisListener(final SourceReceiver sourceReceiver,
final NamingControl namingControl) {
this.sourceReceiver = sourceReceiver;
this.sourceBuilder = new SourceBuilder(namingControl);
}
/**
* Send BrowserAppTraffic, BrowserAppSingleVersionTraffic, BrowserAppPageTraffic and BrowserAppPagePerf scope to the
* receiver.
*/
@Override
public void build() {
// traffic
sourceReceiver.receive(sourceBuilder.toBrowserAppTraffic());
sourceReceiver.receive(sourceBuilder.toBrowserAppSingleVersionTraffic());
sourceReceiver.receive(sourceBuilder.toBrowserAppPageTraffic());
// performance (currently only page level performance data is analyzed)
sourceReceiver.receive(sourceBuilder.toBrowserAppPagePerf());
}
/**
* Parse raw data
*/
@Override
public void parse(final BrowserPerfDataDecorator decorator) {
sourceBuilder.setService(decorator.getService());
sourceBuilder.setServiceVersion(decorator.getServiceVersion());
sourceBuilder.setPatePath(decorator.getPagePath());
// time
sourceBuilder.setTimeBucket(TimeBucket.getMinuteTimeBucket(decorator.getTime()));
// performance related
sourceBuilder.setRedirectTime(decorator.getRedirectTime());
sourceBuilder.setDnsTime(decorator.getDnsTime());
sourceBuilder.setTtfbTime(decorator.getTtfbTime());
sourceBuilder.setTcpTime(decorator.getTcpTime());
sourceBuilder.setTransTime(decorator.getTransTime());
sourceBuilder.setDomAnalysisTime(decorator.getDomAnalysisTime());
sourceBuilder.setFptTime(decorator.getFptTime());
sourceBuilder.setDomReadyTime(decorator.getDomReadyTime());
sourceBuilder.setLoadPageTime(decorator.getLoadPageTime());
sourceBuilder.setResTime(decorator.getResTime());
sourceBuilder.setSslTime(decorator.getSslTime());
sourceBuilder.setTtlTime(decorator.getTtlTime());
sourceBuilder.setFirstPackTime(decorator.getFirstPackTime());
sourceBuilder.setFmpTime(decorator.getFmpTime());
}
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(final ModuleManager moduleManager,
final BrowserServiceModuleConfig moduleConfig) {
return new MultiScopesPerfDataAnalysisListener(sourceReceiver, namingControl);
}
}
}
/*
* 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.receiver.browser.provider.parser.performance.BrowserPerfDataDecorator;
/**
* BrowserPerfDataListener represents the callback when OAP does the browser performance data analysis.
*/
public interface PerfDataAnalysisListener {
/**
* The last step of the analysis process. Typically, the implementations forward the analysis results to the source
* receiver.
*/
void build();
/**
* Parse the raw data from the probe (js-client).
*/
void parse(BrowserPerfDataDecorator decorator);
}
/*
* 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.library.module.ModuleManager;
import org.apache.skywalking.oap.server.receiver.browser.provider.BrowserServiceModuleConfig;
/**
* 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);
}
/*
* 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 lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppPagePerf;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppPageTraffic;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppPerf;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppPerfSource;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppSingleVersionPerf;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppSingleVersionTraffic;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTraffic;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTrafficCategory;
import org.apache.skywalking.oap.server.core.browser.source.BrowserAppTrafficSource;
import org.apache.skywalking.oap.server.core.config.NamingControl;
import org.apache.skywalking.oap.server.core.source.Source;
/**
* Browser traffic and performance related source.
*/
@RequiredArgsConstructor
class SourceBuilder {
private final NamingControl namingControl;
@Getter
private String service;
public void setService(final String service) {
this.service = namingControl.formatServiceName(service);
}
@Getter
private String serviceVersion;
public void setServiceVersion(final String serviceVersion) {
this.serviceVersion = namingControl.formatInstanceName(serviceVersion);
}
@Getter
private String patePath;
public void setPatePath(final String patePath) {
this.patePath = namingControl.formatEndpointName(service, patePath);
}
@Setter
@Getter
private long timeBucket;
// performance data detail
@Setter
@Getter
private int redirectTime;
@Setter
@Getter
private int dnsTime;
@Setter
@Getter
private int ttfbTime;
@Setter
@Getter
private int tcpTime;
@Setter
@Getter
private int transTime;
@Setter
@Getter
private int domAnalysisTime;
@Setter
@Getter
private int fptTime;
@Setter
@Getter
private int domReadyTime;
@Setter
@Getter
private int loadPageTime;
@Setter
@Getter
private int resTime;
@Setter
@Getter
private int sslTime;
@Setter
@Getter
private int ttlTime;
@Setter
@Getter
private int firstPackTime;
@Setter
@Getter
private int fmpTime;
private void toSource(Source source) {
source.setTimeBucket(timeBucket);
}
private void toBrowserAppTrafficSource(BrowserAppTrafficSource source) {
toSource(source);
source.setTrafficCategory(BrowserAppTrafficCategory.NORMAL);
}
/**
* Browser service meta and traffic metrics related source.
*/
BrowserAppTraffic toBrowserAppTraffic() {
BrowserAppTraffic traffic = new BrowserAppTraffic();
traffic.setName(service);
toBrowserAppTrafficSource(traffic);
return traffic;
}
/**
* Browser single version meta and traffic metrics related source.
*/
BrowserAppSingleVersionTraffic toBrowserAppSingleVersionTraffic() {
BrowserAppSingleVersionTraffic traffic = new BrowserAppSingleVersionTraffic();
traffic.setName(serviceVersion);
traffic.setServiceName(service);
toBrowserAppTrafficSource(traffic);
return traffic;
}
/**
* Browser page meta and traffic metrics related source.
*/
BrowserAppPageTraffic toBrowserAppPageTraffic() {
BrowserAppPageTraffic traffic = new BrowserAppPageTraffic();
traffic.setName(patePath);
traffic.setServiceName(service);
toBrowserAppTrafficSource(traffic);
return traffic;
}
private void toBrowserAppPerfSource(BrowserAppPerfSource source) {
toSource(source);
source.setRedirectTime(redirectTime);
source.setDnsTime(dnsTime);
source.setTtfbTime(ttfbTime);
source.setTcpTime(tcpTime);
source.setTransTime(transTime);
source.setDomAnalysisTime(domAnalysisTime);
source.setFptTime(fptTime);
source.setDomReadyTime(domReadyTime);
source.setLoadPageTime(loadPageTime);
source.setResTime(resTime);
source.setSslTime(sslTime);
source.setTtlTime(ttlTime);
source.setFirstPackTime(firstPackTime);
source.setFmpTime(fmpTime);
}
/**
* Browser service performance related source.
*/
BrowserAppPerf toBrowserAppPerf() {
BrowserAppPerf perf = new BrowserAppPerf();
perf.setName(service);
toBrowserAppPerfSource(perf);
return perf;
}
/**
* Browser single version performance related source.
*/
BrowserAppSingleVersionPerf toBrowserAppSingleVersionPerf() {
BrowserAppSingleVersionPerf perf = new BrowserAppSingleVersionPerf();
perf.setName(serviceVersion);
perf.setServiceName(service);
toBrowserAppPerfSource(perf);
return perf;
}
/**
* Browser page performance related source.
*/
BrowserAppPagePerf toBrowserAppPagePerf() {
BrowserAppPagePerf perf = new BrowserAppPagePerf();
perf.setName(patePath);
perf.setServiceName(service);
toBrowserAppPerfSource(perf);
return perf;
}
}
#
# 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.
#
#
org.apache.skywalking.oap.server.receiver.browser.module.BrowserModule
\ No newline at end of file
#
# 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.
#
#
org.apache.skywalking.oap.server.receiver.browser.provider.BrowserModuleProvider
\ No newline at end of file
......@@ -42,6 +42,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDA
import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -64,6 +65,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.TimeSe
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.cache.NetworkAddressAliasEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.AggregationQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.AlarmQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.BrowserLogQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.LogQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.MetadataQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.MetricsQueryEsDAO;
......@@ -168,6 +170,7 @@ public class StorageModuleElasticsearchProvider extends ModuleProvider {
this.registerServiceImplementation(IMetricsQueryDAO.class, new MetricsQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(
ITraceQueryDAO.class, new TraceQueryEsDAO(elasticSearchClient, config.getSegmentQueryMaxSize()));
this.registerServiceImplementation(IBrowserLogQueryDAO.class, new BrowserLogQueryEsDAO(elasticSearchClient));
this.registerServiceImplementation(
IMetadataQueryDAO.class, new MetadataQueryEsDAO(elasticSearchClient, config.getMetadataQueryMaxSize()));
this.registerServiceImplementation(IAggregationQueryDAO.class, new AggregationQueryEsDAO(elasticSearchClient));
......
/*
* 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.storage.plugin.elasticsearch.query;
import com.google.common.base.Strings;
import java.io.IOException;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.browser.manual.errorlog.BrowserErrorLogRecord;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLog;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.MatchCNameBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import static java.util.Objects.nonNull;
public class BrowserLogQueryEsDAO extends EsDAO implements IBrowserLogQueryDAO {
public BrowserLogQueryEsDAO(final ElasticSearchClient client) {
super(client);
}
@Override
public BrowserErrorLogs queryBrowserErrorLogs(final String serviceId,
final String serviceVersionId,
final String pagePathId,
final String pagePath,
final BrowserErrorCategory category,
final long startSecondTB,
final long endSecondTB,
final int limit,
final int from) throws IOException {
SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
sourceBuilder.query(boolQueryBuilder);
if (startSecondTB != 0 && endSecondTB != 0) {
boolQueryBuilder.must().add(
QueryBuilders.rangeQuery(BrowserErrorLogRecord.TIME_BUCKET).gte(startSecondTB).lte(endSecondTB));
}
if (!Strings.isNullOrEmpty(pagePath)) {
String matchCName = MatchCNameBuilder.INSTANCE.build(BrowserErrorLogRecord.PAGE_PATH);
boolQueryBuilder.must().add(QueryBuilders.matchPhraseQuery(matchCName, pagePath));
}
if (StringUtil.isNotEmpty(serviceId)) {
boolQueryBuilder.must().add(QueryBuilders.termQuery(BrowserErrorLogRecord.SERVICE_ID, serviceId));
}
if (StringUtil.isNotEmpty(serviceVersionId)) {
boolQueryBuilder.must()
.add(QueryBuilders.termQuery(BrowserErrorLogRecord.SERVICE_VERSION_ID, serviceVersionId));
}
if (StringUtil.isNotEmpty(pagePathId)) {
boolQueryBuilder.must().add(QueryBuilders.termQuery(BrowserErrorLogRecord.PAGE_PATH_ID, pagePathId));
}
if (nonNull(category)) {
boolQueryBuilder.must()
.add(QueryBuilders.termQuery(BrowserErrorLogRecord.ERROR_CATEGORY, category.getValue()));
}
sourceBuilder.size(limit);
sourceBuilder.from(from);
SearchResponse response = getClient().search(BrowserErrorLogRecord.INDEX_NAME, sourceBuilder);
BrowserErrorLogs logs = new BrowserErrorLogs();
logs.setTotal((int) response.getHits().totalHits);
for (SearchHit searchHit : response.getHits().getHits()) {
String dataBinaryBase64 = (String) searchHit.getSourceAsMap().get(BrowserErrorLogRecord.DATA_BINARY);
if (nonNull(dataBinaryBase64)) {
BrowserErrorLog log = parserDataBinary(dataBinaryBase64);
logs.getLogs().add(log);
}
}
return logs;
}
}
......@@ -40,6 +40,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDA
import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -66,6 +67,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.client.Ela
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.dao.StorageEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.AggregationQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.AlarmQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.BrowserLogQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.LogQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.MetadataQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.MetricsQueryEs7DAO;
......@@ -120,7 +122,7 @@ public class StorageModuleElasticsearch7Provider extends ModuleProvider {
}
if (!StringUtil.isEmpty(config.getSecretsManagementFile())) {
MultipleFilesChangeMonitor monitor = new MultipleFilesChangeMonitor(
10, readableContents -> {
10, readableContents -> {
final byte[] secretsFileContent = readableContents.get(0);
if (secretsFileContent == null) {
return;
......@@ -148,58 +150,62 @@ public class StorageModuleElasticsearch7Provider extends ModuleProvider {
}
elasticSearch7Client = new ElasticSearch7Client(
config.getClusterNodes(), config.getProtocol(), config.getTrustStorePath(), config
.getTrustStorePass(), config.getUser(), config.getPassword(),
indexNameConverters(config.getNameSpace())
config.getClusterNodes(), config.getProtocol(), config.getTrustStorePath(), config
.getTrustStorePass(), config.getUser(), config.getPassword(),
indexNameConverters(config.getNameSpace())
);
this.registerServiceImplementation(
IBatchDAO.class, new BatchProcessEsDAO(elasticSearch7Client, config.getBulkActions(),
config.getFlushInterval(), config.getConcurrentRequests()
));
IBatchDAO.class, new BatchProcessEsDAO(elasticSearch7Client, config.getBulkActions(),
config.getFlushInterval(), config.getConcurrentRequests()
));
this.registerServiceImplementation(StorageDAO.class, new StorageEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(
IHistoryDeleteDAO.class, new HistoryDeleteEsDAO(elasticSearch7Client));
IHistoryDeleteDAO.class, new HistoryDeleteEsDAO(elasticSearch7Client));
this.registerServiceImplementation(
INetworkAddressAliasDAO.class, new NetworkAddressAliasEsDAO(
elasticSearch7Client,
config.getResultWindowMaxSize()
));
INetworkAddressAliasDAO.class, new NetworkAddressAliasEsDAO(
elasticSearch7Client,
config.getResultWindowMaxSize()
));
this.registerServiceImplementation(ITopologyQueryDAO.class, new TopologyQueryEsDAO(elasticSearch7Client));
this.registerServiceImplementation(IMetricsQueryDAO.class, new MetricsQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(
ITraceQueryDAO.class, new TraceQueryEs7DAO(elasticSearch7Client, config.getSegmentQueryMaxSize()));
ITraceQueryDAO.class, new TraceQueryEs7DAO(elasticSearch7Client, config.getSegmentQueryMaxSize()));
this.registerServiceImplementation(IBrowserLogQueryDAO.class, new BrowserLogQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(
IMetadataQueryDAO.class, new MetadataQueryEs7DAO(elasticSearch7Client, config.getMetadataQueryMaxSize()));
IMetadataQueryDAO.class, new MetadataQueryEs7DAO(elasticSearch7Client, config.getMetadataQueryMaxSize()));
this.registerServiceImplementation(
IAggregationQueryDAO.class, new AggregationQueryEs7DAO(elasticSearch7Client));
IAggregationQueryDAO.class, new AggregationQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(IAlarmQueryDAO.class, new AlarmQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new TopNRecordsQueryEsDAO(elasticSearch7Client));
this.registerServiceImplementation(ILogQueryDAO.class, new LogQueryEs7DAO(elasticSearch7Client));
this.registerServiceImplementation(
IProfileTaskQueryDAO.class, new ProfileTaskQueryEsDAO(
elasticSearch7Client,
config.getProfileTaskQueryMaxSize()
));
IProfileTaskQueryDAO.class, new ProfileTaskQueryEsDAO(
elasticSearch7Client,
config.getProfileTaskQueryMaxSize()
));
this.registerServiceImplementation(
IProfileTaskLogQueryDAO.class, new ProfileTaskLogEsDAO(
elasticSearch7Client,
config.getProfileTaskQueryMaxSize()
));
IProfileTaskLogQueryDAO.class, new ProfileTaskLogEsDAO(
elasticSearch7Client,
config.getProfileTaskQueryMaxSize()
));
this.registerServiceImplementation(
IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQueryEs7DAO(
elasticSearch7Client,
config.getProfileTaskQueryMaxSize()
));
IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQueryEs7DAO(
elasticSearch7Client,
config.getProfileTaskQueryMaxSize()
));
this.registerServiceImplementation(
UITemplateManagementDAO.class, new UITemplateManagementEsDAO(elasticSearch7Client));
UITemplateManagementDAO.class, new UITemplateManagementEsDAO(elasticSearch7Client));
}
@Override
public void start() throws ModuleStartException {
MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME).provider().getService(MetricsCreator.class);
HealthCheckMetrics healthChecker = metricCreator.createHealthCheckerGauge("storage_elasticsearch", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE);
MetricsCreator metricCreator = getManager().find(TelemetryModule.NAME)
.provider()
.getService(MetricsCreator.class);
HealthCheckMetrics healthChecker = metricCreator.createHealthCheckerGauge(
"storage_elasticsearch", MetricsTag.EMPTY_KEY, MetricsTag.EMPTY_VALUE);
elasticSearch7Client.registerChecker(healthChecker);
try {
elasticSearch7Client.connect();
......@@ -217,6 +223,6 @@ public class StorageModuleElasticsearch7Provider extends ModuleProvider {
@Override
public String[] requiredModules() {
return new String[]{CoreModule.NAME};
return new String[] {CoreModule.NAME};
}
}
/*
* 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.storage.plugin.elasticsearch7.query;
import com.google.common.base.Strings;
import java.io.IOException;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.browser.manual.errorlog.BrowserErrorLogRecord;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLog;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.MatchCNameBuilder;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.BrowserLogQueryEsDAO;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import static java.util.Objects.nonNull;
public class BrowserLogQueryEs7DAO extends BrowserLogQueryEsDAO {
public BrowserLogQueryEs7DAO(final ElasticSearchClient client) {
super(client);
}
@Override
public BrowserErrorLogs queryBrowserErrorLogs(final String serviceId,
final String serviceVersionId,
final String pagePathId,
final String pagePath,
final BrowserErrorCategory category,
final long startSecondTB,
final long endSecondTB,
final int limit,
final int from) throws IOException {
SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
sourceBuilder.query(boolQueryBuilder);
if (startSecondTB != 0 && endSecondTB != 0) {
boolQueryBuilder.must().add(
QueryBuilders.rangeQuery(BrowserErrorLogRecord.TIME_BUCKET).gte(startSecondTB).lte(endSecondTB));
}
if (!Strings.isNullOrEmpty(pagePath)) {
String matchCName = MatchCNameBuilder.INSTANCE.build(BrowserErrorLogRecord.PAGE_PATH);
boolQueryBuilder.must().add(QueryBuilders.matchPhraseQuery(matchCName, pagePath));
}
if (StringUtil.isNotEmpty(serviceId)) {
boolQueryBuilder.must().add(QueryBuilders.termQuery(BrowserErrorLogRecord.SERVICE_ID, serviceId));
}
if (StringUtil.isNotEmpty(serviceVersionId)) {
boolQueryBuilder.must()
.add(QueryBuilders.termQuery(BrowserErrorLogRecord.SERVICE_VERSION_ID, serviceVersionId));
}
if (StringUtil.isNotEmpty(pagePathId)) {
boolQueryBuilder.must().add(QueryBuilders.termQuery(BrowserErrorLogRecord.PAGE_PATH_ID, pagePathId));
}
if (nonNull(category)) {
boolQueryBuilder.must()
.add(QueryBuilders.termQuery(BrowserErrorLogRecord.ERROR_CATEGORY, category.getValue()));
}
sourceBuilder.size(limit);
sourceBuilder.from(from);
SearchResponse response = getClient().search(BrowserErrorLogRecord.INDEX_NAME, sourceBuilder);
BrowserErrorLogs logs = new BrowserErrorLogs();
logs.setTotal((int) response.getHits().getTotalHits().value);
for (SearchHit searchHit : response.getHits().getHits()) {
String dataBinaryBase64 = (String) searchHit.getSourceAsMap().get(BrowserErrorLogRecord.DATA_BINARY);
if (nonNull(dataBinaryBase64)) {
BrowserErrorLog log = parserDataBinary(dataBinaryBase64);
logs.getLogs().add(log);
}
}
return logs;
}
}
......@@ -33,6 +33,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDA
import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -49,6 +50,7 @@ import org.apache.skywalking.oap.server.storage.plugin.influxdb.base.HistoryDele
import org.apache.skywalking.oap.server.storage.plugin.influxdb.base.InfluxStorageDAO;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.AggregationQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.AlarmQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.BrowserLogQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.LogQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.MetadataQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.MetricsQuery;
......@@ -98,6 +100,7 @@ public class InfluxStorageProvider extends ModuleProvider {
this.registerServiceImplementation(ITopologyQueryDAO.class, new TopologyQuery(client));
this.registerServiceImplementation(IMetricsQueryDAO.class, new MetricsQuery(client));
this.registerServiceImplementation(ITraceQueryDAO.class, new TraceQuery(client));
this.registerServiceImplementation(IBrowserLogQueryDAO.class, new BrowserLogQuery(client));
this.registerServiceImplementation(IAggregationQueryDAO.class, new AggregationQuery(client));
this.registerServiceImplementation(IAlarmQueryDAO.class, new AlarmQuery(client));
this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new TopNRecordsQuery(client));
......@@ -105,12 +108,12 @@ public class InfluxStorageProvider extends ModuleProvider {
this.registerServiceImplementation(IProfileTaskQueryDAO.class, new ProfileTaskQuery(client));
this.registerServiceImplementation(
IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQuery(client));
IProfileThreadSnapshotQueryDAO.class, new ProfileThreadSnapshotQuery(client));
this.registerServiceImplementation(
IProfileTaskLogQueryDAO.class, new ProfileTaskLogQuery(client, config.getFetchTaskLogMaxSize()));
IProfileTaskLogQueryDAO.class, new ProfileTaskLogQuery(client, config.getFetchTaskLogMaxSize()));
this.registerServiceImplementation(
IHistoryDeleteDAO.class, new HistoryDeleteDAO(client));
IHistoryDeleteDAO.class, new HistoryDeleteDAO(client));
this.registerServiceImplementation(UITemplateManagementDAO.class, new UITemplateManagementDAOImpl(client));
}
......@@ -133,6 +136,6 @@ public class InfluxStorageProvider extends ModuleProvider {
@Override
public String[] requiredModules() {
return new String[]{CoreModule.NAME};
return new String[] {CoreModule.NAME};
}
}
/*
* 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.storage.plugin.influxdb.query;
import java.io.IOException;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.browser.manual.errorlog.BrowserErrorLogRecord;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLog;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.influxdb.querybuilder.SelectQueryImpl;
import org.influxdb.querybuilder.WhereQueryImpl;
import static java.util.Objects.nonNull;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.contains;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.eq;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.gte;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.lte;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.select;
@Slf4j
@RequiredArgsConstructor
public class BrowserLogQuery implements IBrowserLogQueryDAO {
private final InfluxClient client;
@Override
public BrowserErrorLogs queryBrowserErrorLogs(final String serviceId,
final String serviceVersionId,
final String pagePathId,
final String pagePath,
final BrowserErrorCategory category,
final long startSecondTB,
final long endSecondTB,
final int limit,
final int from) throws IOException {
WhereQueryImpl<SelectQueryImpl> recallQuery = select()
.function(InfluxConstants.SORT_DES, BrowserErrorLogRecord.TIMESTAMP, limit + from)
.column(BrowserErrorLogRecord.DATA_BINARY)
.from(
client.getDatabase(),
BrowserErrorLogRecord.INDEX_NAME
).where();
if (startSecondTB != 0 && endSecondTB != 0) {
recallQuery.and(gte(BrowserErrorLogRecord.TIME_BUCKET, startSecondTB))
.and(lte(BrowserErrorLogRecord.TIME_BUCKET, endSecondTB));
}
if (StringUtil.isNotEmpty(serviceId)) {
recallQuery.and(eq(BrowserErrorLogRecord.SERVICE_ID, serviceId));
}
if (StringUtil.isNotEmpty(serviceVersionId)) {
recallQuery.and(eq(BrowserErrorLogRecord.SERVICE_VERSION_ID, serviceVersionId));
}
if (StringUtil.isNotEmpty(pagePathId)) {
recallQuery.and(eq(BrowserErrorLogRecord.PAGE_PATH_ID, pagePathId));
}
if (nonNull(category)) {
recallQuery.and(eq(BrowserErrorLogRecord.ERROR_CATEGORY, category.getValue()));
}
if (StringUtil.isNotEmpty(pagePath)) {
recallQuery.and(contains(BrowserErrorLogRecord.PAGE_PATH, pagePath.replaceAll("/", "\\\\/")));
}
WhereQueryImpl<SelectQueryImpl> countQuery = select()
.count(BrowserErrorLogRecord.SERVICE_ID)
.from(client.getDatabase(), BrowserErrorLogRecord.INDEX_NAME)
.where();
recallQuery.getClauses().forEach(countQuery::where);
Query query = new Query(countQuery.getCommand() + recallQuery.getCommand());
List<QueryResult.Result> results = client.query(query);
if (log.isDebugEnabled()) {
log.debug("SQL: {} result set: {}", query.getCommand(), results);
}
if (results.size() != 2) {
throw new IOException("Expecting to get 2 Results, but it is " + results.size());
}
List<QueryResult.Series> counter = results.get(0).getSeries();
List<QueryResult.Series> result = results.get(1).getSeries();
if (result == null || result.isEmpty()) {
return new BrowserErrorLogs();
}
BrowserErrorLogs logs = new BrowserErrorLogs();
logs.setTotal(((Number) counter.get(0).getValues().get(0).get(1)).intValue());
result.get(0).getValues().stream().sorted((a, b) -> {
// Have to re-sort here. Because the function, top()/bottom(), get the result ordered by the `time`.
return Long.compare(((Number) b.get(1)).longValue(), ((Number) a.get(1)).longValue());
}).skip(from).forEach(values -> {
String dataBinaryBase64 = (String) values.get(2);
if (nonNull(dataBinaryBase64)) {
BrowserErrorLog log = parserDataBinary(dataBinaryBase64);
logs.getLogs().add(log);
}
});
return logs;
}
}
......@@ -83,7 +83,7 @@ public class MetadataQuery implements IMetadataQueryDAO {
public List<Service> getAllBrowserServices(long startTimestamp, long endTimestamp) throws IOException {
WhereQueryImpl<SelectQueryImpl> query = select(ID_COLUMN, NAME)
.from(client.getDatabase(), ServiceTraffic.INDEX_NAME)
.where(eq(InfluxConstants.TagName.NODE_TYPE, String.valueOf(NodeType.Normal.value())));
.where(eq(InfluxConstants.TagName.NODE_TYPE, String.valueOf(NodeType.Browser.value())));
return buildServices(query);
}
......
......@@ -36,6 +36,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDA
import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -51,6 +52,7 @@ import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedExcepti
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2AggregationQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2AlarmQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BatchDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BrowserLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2HistoryDeleteDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2LogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2MetadataQueryDAO;
......@@ -129,6 +131,7 @@ public class H2StorageProvider extends ModuleProvider {
config.getMaxSizeOfArrayColumn(),
config.getNumOfSearchableValuesPerTag()
));
this.registerServiceImplementation(IBrowserLogQueryDAO.class, new H2BrowserLogQueryDAO(h2Client));
this.registerServiceImplementation(
IMetadataQueryDAO.class, new H2MetadataQueryDAO(h2Client, config.getMetadataQueryMaxSize()));
this.registerServiceImplementation(IAggregationQueryDAO.class, new H2AggregationQueryDAO(h2Client));
......
/*
* 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.storage.plugin.jdbc.h2.dao;
import com.google.common.base.Strings;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.browser.manual.errorlog.BrowserErrorLogRecord;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLog;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import static java.util.Objects.nonNull;
@RequiredArgsConstructor
public class H2BrowserLogQueryDAO implements IBrowserLogQueryDAO {
private final JDBCHikariCPClient h2Client;
@Override
public BrowserErrorLogs queryBrowserErrorLogs(String serviceId,
String serviceVersionId,
String pagePathId,
String pagePath,
BrowserErrorCategory category,
long startSecondTB,
long endSecondTB,
int limit,
int from) throws IOException {
StringBuilder sql = new StringBuilder();
List<Object> parameters = new ArrayList<>(9);
sql.append("from ").append(BrowserErrorLogRecord.INDEX_NAME)
.append(" where ").append(" 1=1 ");
if (startSecondTB != 0 && endSecondTB != 0) {
sql.append(" and ").append(BrowserErrorLogRecord.TIME_BUCKET).append(" >= ?");
parameters.add(startSecondTB);
sql.append(" and ").append(BrowserErrorLogRecord.TIME_BUCKET).append(" <= ?");
parameters.add(endSecondTB);
}
if (StringUtil.isNotEmpty(serviceId)) {
sql.append(" and ").append(BrowserErrorLogRecord.SERVICE_ID).append(" = ?");
parameters.add(serviceId);
}
if (StringUtil.isNotEmpty(serviceVersionId)) {
sql.append(" and ").append(BrowserErrorLogRecord.SERVICE_VERSION_ID).append(" = ?");
parameters.add(serviceVersionId);
}
if (StringUtil.isNotEmpty(pagePathId)) {
sql.append(" and ").append(BrowserErrorLogRecord.PAGE_PATH_ID).append(" = ?");
parameters.add(pagePathId);
}
if (nonNull(category)) {
sql.append(" and ").append(BrowserErrorLogRecord.ERROR_CATEGORY).append(" = ?");
parameters.add(category.getValue());
}
if (!Strings.isNullOrEmpty(pagePath)) {
sql.append(" and ").append(BrowserErrorLogRecord.PAGE_PATH).append(" like concat('%',?,'%')");
parameters.add(pagePath);
}
BrowserErrorLogs logs = new BrowserErrorLogs();
try (Connection connection = h2Client.getConnection()) {
try (ResultSet resultSet = h2Client.executeQuery(connection, buildCountStatement(sql.toString()), parameters
.toArray(new Object[0]))) {
while (resultSet.next()) {
logs.setTotal(resultSet.getInt("total"));
}
}
buildLimit(sql, from, limit);
try (ResultSet resultSet = h2Client.executeQuery(
connection, "select " + BrowserErrorLogRecord.DATA_BINARY + " " + sql.toString(),
parameters.toArray(new Object[0])
)) {
while (resultSet.next()) {
String dataBinaryBase64 = resultSet.getString(BrowserErrorLogRecord.DATA_BINARY);
if (nonNull(dataBinaryBase64)) {
BrowserErrorLog log = parserDataBinary(dataBinaryBase64);
logs.getLogs().add(log);
}
}
}
} catch (SQLException e) {
throw new IOException(e);
}
return logs;
}
protected String buildCountStatement(String sql) {
return "select count(1) total from (select 1 " + sql + " )";
}
protected void buildLimit(StringBuilder sql, int from, int limit) {
sql.append(" limit ").append(limit);
sql.append(" offset ").append(from);
}
}
......@@ -35,6 +35,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileTaskQueryDA
import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -117,6 +118,7 @@ public class MySQLStorageProvider extends ModuleProvider {
config.getNumOfSearchableValuesPerTag()
)
);
this.registerServiceImplementation(IBrowserLogQueryDAO.class, new MysqlBrowserLogQueryDAO(mysqlClient));
this.registerServiceImplementation(
IMetadataQueryDAO.class, new H2MetadataQueryDAO(mysqlClient, config.getMetadataQueryMaxSize()));
this.registerServiceImplementation(IAggregationQueryDAO.class, new MySQLAggregationQueryDAO(mysqlClient));
......
/*
* 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.storage.plugin.jdbc.mysql;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BrowserLogQueryDAO;
public class MysqlBrowserLogQueryDAO extends H2BrowserLogQueryDAO {
public MysqlBrowserLogQueryDAO(final JDBCHikariCPClient h2Client) {
super(h2Client);
}
@Override
protected String buildCountStatement(String sql) {
return "select count(1) total " + sql;
}
@Override
protected void buildLimit(StringBuilder sql, int from, int limit) {
sql.append(" limit ").append(from).append(", ").append(limit);
}
}
......@@ -38,6 +38,7 @@ import org.apache.skywalking.oap.server.core.oal.rt.OALEngineLoaderService;
import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
import org.apache.skywalking.oap.server.core.query.BrowserLogQueryService;
import org.apache.skywalking.oap.server.core.query.LogQueryService;
import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
......@@ -146,6 +147,7 @@ public class MockCoreModuleProvider extends CoreModuleProvider {
this.registerServiceImplementation(MetricsMetadataQueryService.class, new MetricsMetadataQueryService());
this.registerServiceImplementation(MetricsQueryService.class, new MetricsQueryService(getManager()));
this.registerServiceImplementation(TraceQueryService.class, new TraceQueryService(getManager()));
this.registerServiceImplementation(BrowserLogQueryService.class, new BrowserLogQueryService(getManager()));
this.registerServiceImplementation(LogQueryService.class, new LogQueryService(getManager()));
this.registerServiceImplementation(MetadataQueryService.class, new MetadataQueryService(getManager()));
this.registerServiceImplementation(AggregationQueryService.class, new AggregationQueryService(getManager()));
......
......@@ -25,14 +25,18 @@ import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.e2e.browser.BrowserErrorLog;
import org.apache.skywalking.e2e.browser.BrowserErrorLogQuery;
import org.apache.skywalking.e2e.browser.BrowserErrorLogsData;
import org.apache.skywalking.e2e.metrics.Metrics;
import org.apache.skywalking.e2e.metrics.MetricsData;
import org.apache.skywalking.e2e.metrics.MetricsQuery;
import org.apache.skywalking.e2e.metrics.MultiMetricsData;
import org.apache.skywalking.e2e.metrics.ReadLabeledMetricsData;
import org.apache.skywalking.e2e.metrics.ReadMetricsQuery;
import org.apache.skywalking.e2e.metrics.ReadMetrics;
import org.apache.skywalking.e2e.metrics.ReadMetricsData;
import org.apache.skywalking.e2e.metrics.ReadMetricsQuery;
import org.apache.skywalking.e2e.service.Service;
import org.apache.skywalking.e2e.service.ServicesData;
import org.apache.skywalking.e2e.service.ServicesQuery;
......@@ -43,8 +47,8 @@ import org.apache.skywalking.e2e.service.instance.InstancesQuery;
import org.apache.skywalking.e2e.topo.ServiceInstanceTopology;
import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyQuery;
import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyResponse;
import org.apache.skywalking.e2e.topo.Topology;
import org.apache.skywalking.e2e.topo.TopoQuery;
import org.apache.skywalking.e2e.topo.Topology;
import org.apache.skywalking.e2e.topo.TopologyResponse;
import org.apache.skywalking.e2e.trace.Trace;
import org.apache.skywalking.e2e.trace.TracesData;
......@@ -56,8 +60,6 @@ import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import lombok.extern.slf4j.Slf4j;
@SuppressWarnings("UnstableApiUsage")
@Slf4j
public class SimpleQueryClient {
......@@ -100,8 +102,41 @@ public class SimpleQueryClient {
return Objects.requireNonNull(responseEntity.getBody()).getData().getTraces().getData();
}
public List<BrowserErrorLog> browserErrorLogs(final BrowserErrorLogQuery query) throws Exception {
final URL queryFileUrl = Resources.getResource("browser-error-logs.gql");
final String queryString = Resources.readLines(queryFileUrl, StandardCharsets.UTF_8)
.stream()
.filter(it -> !it.startsWith("#"))
.collect(Collectors.joining())
.replace("{start}", query.start())
.replace("{end}", query.end())
.replace("{step}", query.step())
.replace("{pageNum}", query.pageNum())
.replace("{pageSize}", query.pageSize())
.replace("{needTotal}", query.needTotal());
final ResponseEntity<GQLResponse<BrowserErrorLogsData>> responseEntity = restTemplate.exchange(
new RequestEntity<>(queryString, HttpMethod.POST, URI.create(endpointUrl)),
new ParameterizedTypeReference<GQLResponse<BrowserErrorLogsData>>() {
}
);
if (responseEntity.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException("Response status != 200, actual: " + responseEntity.getStatusCode());
}
return Objects.requireNonNull(responseEntity.getBody().getData().getLogs().getData());
}
public List<Service> services(final ServicesQuery query) throws Exception {
final URL queryFileUrl = Resources.getResource("services.gql");
return services(query, "services.gql");
}
public List<Service> browserServices(final ServicesQuery query) throws Exception {
return services(query, "browser-services.gql");
}
private List<Service> services(final ServicesQuery query, String gql) throws Exception {
final URL queryFileUrl = Resources.getResource(gql);
final String queryString = Resources.readLines(queryFileUrl, StandardCharsets.UTF_8)
.stream()
.filter(it -> !it.startsWith("#"))
......
/*
* 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.e2e.browser;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class BrowserErrorLog {
private String service;
private String serviceVersion;
private Long time;
private String pagePath;
private String category;
private String grade;
private String message;
private Integer line;
private Integer col;
private String stack;
private String errorUrl;
private boolean firstReportedError;
}
/*
* 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.e2e.browser;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.apache.skywalking.e2e.verification.AbstractMatcher;
import static java.util.Objects.nonNull;
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class BrowserErrorLogMatcher extends AbstractMatcher<BrowserErrorLog> {
private String service;
private String serviceVersion;
private String time;
private String pagePath;
private String category;
private String grade;
private String message;
private String line;
private String col;
private String stack;
private String errorUrl;
private String firstReportedError;
@Override
public void verify(final BrowserErrorLog log) {
if (nonNull(getService())) {
doVerify(getService(), log.getService());
}
if (nonNull(getServiceVersion())) {
doVerify(getServiceVersion(), log.getServiceVersion());
}
if (nonNull(getTime())) {
doVerify(getTime(), String.valueOf(log.getTime()));
}
if (nonNull(getPagePath())) {
doVerify(getPagePath(), log.getPagePath());
}
if (nonNull(getCategory())) {
doVerify(getCategory(), log.getCategory());
}
if (nonNull(getGrade())) {
doVerify(getGrade(), log.getGrade());
}
if (nonNull(getMessage())) {
doVerify(getMessage(), log.getMessage());
}
if (nonNull(getLine())) {
doVerify(getLine(), String.valueOf(log.getLine()));
}
if (nonNull(getCol())) {
doVerify(getCol(), String.valueOf(log.getCol()));
}
if (nonNull(getStack())) {
doVerify(getStack(), log.getStack());
}
if (nonNull(getErrorUrl())) {
doVerify(getErrorUrl(), log.getErrorUrl());
}
if (nonNull(getFirstReportedError())) {
doVerify(getFirstReportedError(), String.valueOf(log.isFirstReportedError()));
}
}
}
/*
* 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.e2e.browser;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.skywalking.e2e.AbstractQuery;
@Setter
@Getter
@Accessors(chain = true)
public class BrowserErrorLogQuery extends AbstractQuery<BrowserErrorLogQuery> {
private String pageNum = "1";
private String pageSize = "15";
private String needTotal = "true";
public String pageNum() {
return pageNum;
}
public String pageSize() {
return pageSize;
}
public String needTotal() {
return needTotal;
}
}
/*
* 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.e2e.browser;
import java.util.List;
import lombok.Data;
@Data
public class BrowserErrorLogs {
private List<BrowserErrorLog> data;
}
/*
* 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.e2e.browser;
import lombok.Data;
@Data
public class BrowserErrorLogsData {
private BrowserErrorLogs logs;
}
/*
* 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.e2e.browser;
import java.util.LinkedList;
import java.util.List;
import lombok.Data;
import static org.assertj.core.api.Assertions.fail;
@Data
public class BrowserErrorLogsMatcher {
private List<BrowserErrorLogMatcher> logs;
public BrowserErrorLogsMatcher() {
this.logs = new LinkedList<>();
}
public void verifyLoosely(final List<BrowserErrorLog> logs) {
for (final BrowserErrorLogMatcher matcher : getLogs()) {
boolean matched = false;
for (final BrowserErrorLog log : logs) {
try {
matcher.verify(log);
matched = true;
} catch (Throwable throwable) {
}
}
if (!matched) {
fail("\nExpected: %s\n Actual: %s", getLogs(), logs);
}
}
}
}
/*
* 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.e2e.metrics;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.apache.skywalking.e2e.AbstractQuery;
@Data
@Accessors(fluent = true)
@EqualsAndHashCode(callSuper = true)
public class BrowserMetricsQuery extends AbstractQuery<BrowserMetricsQuery> {
public static final String BROWSER_APP_PV = "browser_app_pv";
public static final String BROWSER_APP_ERROR_RATE = "browser_app_error_rate";
public static final String BROWSER_APP_ERROR_SUM = "browser_app_error_sum";
public static final String[] ALL_BROWSER_METRICS = {
BROWSER_APP_PV,
BROWSER_APP_ERROR_SUM,
BROWSER_APP_ERROR_RATE
};
public static final String BROWSER_APP_SINGLE_VERSION_PV = "browser_app_single_version_pv";
public static final String BROWSER_APP_SINGLE_VERSION_ERROR_RATE = "browser_app_single_version_error_rate";
public static final String BROWSER_APP_SINGLE_VERSION_ERROR_SUM = "browser_app_single_version_error_sum";
public static final String[] ALL_BROWSER_SINGLE_VERSION_METRICS = {
BROWSER_APP_SINGLE_VERSION_PV,
BROWSER_APP_SINGLE_VERSION_ERROR_RATE,
BROWSER_APP_SINGLE_VERSION_ERROR_SUM
};
public static final String BROWSER_APP_PAGE_PV = "browser_app_page_pv";
public static final String BROWSER_APP_PAGE_ERROR_RATE = "browser_app_page_error_rate";
public static final String BROWSER_APP_PAGE_ERROR_SUM = "browser_app_page_error_sum";
public static final String BROWSER_APP_PAGE_AJAX_ERROR_SUM = "browser_app_page_ajax_error_sum";
public static final String BROWSER_APP_PAGE_RESOURCE_ERROR_SUM = "browser_app_page_resource_error_sum";
public static final String BROWSER_APP_PAGE_JS_ERROR_SUM = "browser_app_page_js_error_sum";
public static final String BROWSER_APP_PAGE_UNKNOWN_ERROR_SUM = "browser_app_page_unknown_error_sum";
public static final String BROWSER_APP_PAGE_REDIRECT_AVG = "browser_app_page_redirect_avg";
public static final String BROWSER_APP_PAGE_DNS_AVG = "browser_app_page_dns_avg";
public static final String BROWSER_APP_PAGE_TTFB_AVG = "browser_app_page_ttfb_avg";
public static final String BROWSER_APP_PAGE_TCP_AVG = "browser_app_page_tcp_avg";
public static final String BROWSER_APP_PAGE_TRANS_AVG = "browser_app_page_trans_avg";
public static final String BROWSER_APP_PAGE_DOM_ANALYSIS_AVG = "browser_app_page_dom_analysis_avg";
public static final String BROWSER_APP_PAGE_FPT_AVG = "browser_app_page_fpt_avg";
public static final String BROWSER_APP_PAGE_DOM_READY_AVG = "browser_app_page_dom_ready_avg";
public static final String BROWSER_APP_PAGE_LOAD_PAGE_AVG = "browser_app_page_load_page_avg";
public static final String BROWSER_APP_PAGE_RES_AVG = "browser_app_page_res_avg";
public static final String BROWSER_APP_PAGE_SSL_AVG = "browser_app_page_ssl_avg";
public static final String BROWSER_APP_PAGE_TTL_AVG = "browser_app_page_ttl_avg";
public static final String BROWSER_APP_PAGE_FIRST_PACK_AVG = "browser_app_page_first_pack_avg";
public static final String BROWSER_APP_PAGE_FMP_AVG = "browser_app_page_fmp_avg";
public static final String[] ALL_BROWSER_PAGE_METRICS = {
BROWSER_APP_PAGE_PV,
BROWSER_APP_PAGE_ERROR_RATE,
BROWSER_APP_PAGE_ERROR_SUM,
BROWSER_APP_PAGE_AJAX_ERROR_SUM,
BROWSER_APP_PAGE_RESOURCE_ERROR_SUM,
BROWSER_APP_PAGE_JS_ERROR_SUM,
BROWSER_APP_PAGE_UNKNOWN_ERROR_SUM,
BROWSER_APP_PAGE_REDIRECT_AVG,
BROWSER_APP_PAGE_DNS_AVG,
BROWSER_APP_PAGE_TTFB_AVG,
BROWSER_APP_PAGE_TCP_AVG,
BROWSER_APP_PAGE_TRANS_AVG,
BROWSER_APP_PAGE_DOM_ANALYSIS_AVG,
BROWSER_APP_PAGE_FPT_AVG,
BROWSER_APP_PAGE_DOM_READY_AVG,
BROWSER_APP_PAGE_LOAD_PAGE_AVG,
BROWSER_APP_PAGE_RES_AVG,
BROWSER_APP_PAGE_SSL_AVG,
BROWSER_APP_PAGE_TTL_AVG,
BROWSER_APP_PAGE_FIRST_PACK_AVG,
BROWSER_APP_PAGE_FMP_AVG
};
public static final String BROWSER_APP_PAGE_FPT_PERCENTILE = "browser_app_page_fpt_percentile";
public static final String BROWSER_APP_PAGE_DOM_READY_PERCENTILE = "browser_app_page_dom_ready_percentile";
public static final String BROWSER_APP_PAGE_LOAD_PAGE_PERCENTILE = "browser_app_page_load_page_percentile";
public static final String BROWSER_APP_PAGE_TTL_PERCENTILE = "browser_app_page_ttl_percentile";
public static final String BROWSER_APP_PAGE_FIRST_PACK_PERCENTILE = "browser_app_page_first_pack_percentile";
public static final String BROWSER_APP_PAGE_FMP_PERCENTILE = "browser_app_page_fmp_percentile";
public static final String[] ALL_BROWSER_PAGE_MULTIPLE_LINEAR_METRICS = {
BROWSER_APP_PAGE_FPT_PERCENTILE,
BROWSER_APP_PAGE_TTL_PERCENTILE,
BROWSER_APP_PAGE_DOM_READY_PERCENTILE,
BROWSER_APP_PAGE_LOAD_PAGE_PERCENTILE,
BROWSER_APP_PAGE_FIRST_PACK_PERCENTILE,
BROWSER_APP_PAGE_FMP_PERCENTILE
};
}
......@@ -19,10 +19,10 @@
package org.apache.skywalking.e2e.metrics;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.e2e.SimpleQueryClient;
import org.apache.skywalking.e2e.utils.Times;
@Slf4j
public class MetricsMatcher {
......@@ -46,7 +46,7 @@ public class MetricsMatcher {
new MetricsQuery().stepByMinute()
.metricsName(metricName)
.start(minutesAgo)
.end(LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1))
.end(Times.now().plusMinutes(1))
.id(id));
LOGGER.info("{}: {}", metricName, metrics);
AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new AtLeastOneOfMetricsMatcher();
......@@ -67,6 +67,13 @@ public class MetricsMatcher {
}
}
public static void verifyPercentileMetrics(final SimpleQueryClient queryClient,
final String metricName,
final String id,
final LocalDateTime minutesAgo) throws Exception {
verifyPercentileMetrics(queryClient, metricName, id, minutesAgo, 0, null);
}
public static void verifyPercentileMetrics(final SimpleQueryClient queryClient,
final String metricName,
final String id,
......@@ -79,7 +86,7 @@ public class MetricsMatcher {
new MetricsQuery().stepByMinute()
.metricsName(metricName)
.start(minutesAgo)
.end(LocalDateTime.now(ZoneOffset.UTC).plusMinutes(1))
.end(Times.now().plusMinutes(1))
.id(id), "5");
LOGGER.info("{}: {}", metricName, metricsArray);
AtLeastOneOfMetricsMatcher matcher = new AtLeastOneOfMetricsMatcher();
......
......@@ -6,14 +6,13 @@
* (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.e2e.utils;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册