Add data-generator module to run OAP in testing mode, generating mock data for testing (#8725)

This commit is contained in:
kezhenxu94 2022-04-23 17:00:32 +08:00 committed by GitHub
parent d2fcd83018
commit 3256b6c9d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 2350 additions and 7 deletions

View File

@ -41,6 +41,7 @@ DOCKER_BUILD_TOP:=${CONTEXT}/docker_build
HUB ?= skywalking
OAP_NAME ?= oap
UI_NAME ?= ui
DATA_GENERATOR_NAME ?= data-generator
TAG ?= latest
.PHONY: docker docker.all
@ -57,6 +58,7 @@ BUILD_ARGS := $(BUILD_ARGS) --build-arg DIST=$(DIST) --build-arg SKYWALKING_CLI_
%.ui: NAME = $(UI_NAME)
%.oap: NAME = $(OAP_NAME)
%.data-generator: NAME = $(DATA_GENERATOR_NAME)
docker.%: PLATFORMS =
docker.%: LOAD_OR_PUSH = --load
@ -86,4 +88,4 @@ define DOCKER_RULE
-t $(HUB)/$(NAME):latest \
$(DOCKER_BUILD_TOP)/$(NAME)
docker buildx rm skywalking_main || true
endef
endef

View File

@ -82,6 +82,31 @@
<outputDirectory>oap-libs</outputDirectory>
</fileSet>
<!-- data generator -->
<fileSet>
<directory>${project.basedir}/../oap-server/server-tools/data-generator/target/</directory>
<includes>
<include>data-generator-${project.version}.jar</include>
</includes>
<outputDirectory>oap-libs</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.basedir}/../oap-server/server-tools/data-generator/src/main/assembly/bin</directory>
<outputDirectory>tools/data-generator/bin</outputDirectory>
<includes>
<include>*.sh</include>
</includes>
<fileMode>0755</fileMode>
</fileSet>
<fileSet>
<directory>${project.basedir}/../oap-server/server-tools/data-generator/src/main/resources</directory>
<outputDirectory>tools/data-generator/config</outputDirectory>
<includes>
<include>application.yml</include>
</includes>
</fileSet>
<!-- data generator -->
<!-- Profile exporter tools -->
<fileSet>
<directory>${project.basedir}/../tools/profile-exporter</directory>

View File

@ -0,0 +1,52 @@
# 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.
ARG BASE_IMAGE='eclipse-temurin:11-jre'
ARG SKYWALKING_CLI_VERSION
FROM apache/skywalking-cli:$SKYWALKING_CLI_VERSION as cli
FROM $BASE_IMAGE
WORKDIR /skywalking
ENV JAVA_OPTS=" -Xms2G "
ARG DIST
COPY "$DIST" .
RUN set -ex; \
tar -xzf "$DIST" --strip 1; \
rm -rf "$DIST"; \
rm -rf "config/log4j2.xml"; \
rm -rf "bin"; \
rm -rf "webapp"; \
rm -rf "agent"; \
mkdir "bin";
COPY --from=cli /swctl ./bin
COPY log4j2.xml config/
COPY docker-entrypoint.sh .
RUN mkdir ext-config; \
mkdir ext-libs;
EXPOSE 12800 11800 1234
ENTRYPOINT ["bash", "docker-entrypoint.sh"]

View File

@ -0,0 +1,46 @@
#!/bin/sh
# 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.
set -e
echo "[Entrypoint] Apache SkyWalking Data Generator Docker Image"
EXT_LIB_DIR=/skywalking/ext-libs
EXT_CONFIG_DIR=/skywalking/ext-config
# Override default application.yml with application.yml in the data generator module
cp -vfRL tools/data-generator/config/application.yml config/
# Override configuration files
if [ "$(ls -A $EXT_CONFIG_DIR)" ]; then
cp -vfRL ${EXT_CONFIG_DIR}/* config/
fi
CLASSPATH="config:$CLASSPATH"
for i in oap-libs/*.jar
do
CLASSPATH="$i:$CLASSPATH"
done
for i in "${EXT_LIB_DIR}"/*.jar
do
CLASSPATH="$i:$CLASSPATH"
done
set -ex
exec java ${JAVA_OPTS} -classpath ${CLASSPATH} org.apache.skywalking.starter.DataGeneratorStartUp "$@"

View File

@ -0,0 +1,35 @@
<?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.
~
-->
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout>
<LevelPatternSelector defaultPattern="%d %c %L [%t] %-5p %x - %m%n">
<PatternMatch key="ERROR" pattern="%d %c %L [%t] %-5p %x - [%swversion] %m%n" />
</LevelPatternSelector>
</PatternLayout>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>

View File

@ -125,7 +125,7 @@
* Add `Column.shardingKeyIdx` for column definition for BanyanDB.
```
Sharding key is used to group time series data per metric of one entity in one place (same sharding and/or same
Sharding key is used to group time series data per metric of one entity in one place (same sharding and/or same
row for column-oriented database).
For example,
ServiceA's traffic gauge, service call per minute, includes following timestamp values, then it should be sharded by service ID

View File

@ -27,6 +27,7 @@
priority**](https://github.com/apache/skywalking/pull/8664) to avoid consuming issues.
* Fix the problem that some configurations (such as group.id) did not take effect due to the override order when using the kafkaConsumerConfig property to extend the configuration in Kafka Fetcher.
* Remove build time from the OAP version.
* Add data-generator module to run OAP in testing mode, generating mock data for testing.
#### UI

View File

@ -0,0 +1,207 @@
# Mock data generator for testing
In 9.1.0, SkyWalking adds a module to generate mock data for testing. You can use this module to generate
mock data that will be sent to the storage.
To start the data generator, execute the script `tools/data-generator/bin/start.sh`.
Note that SkyWalking doesn't release a Docker image for this module, but you can still build it yourselves
by running the commands:
```shell
# build a Docker image for local use
make docker.data-generator
# or push to your registry
export HUB=<your-registry>
make push.docker.data-generator
```
Currently the module can generate two kinds of SkyWalking data, segments and logs. For each type,
there are some generators that can be used to fill the fields.
## Generate mock data
To generate mock data, `POST` a request to URL path `/mock-data/segments/tasks` (segments) or
`/mock-data/logs/tasks` (logs) with a generator template:
```shell
curl -XPOST 'http://localhost:12800/mock-data/segments/tasks?size=20' -H'Content-Type: application/json' -d "@segment-template.json"
curl -XPOST 'http://localhost:12800/mock-data/logs/tasks?size=20' -H'Content-Type: application/json' -d "@logs-template.json"
```
There are two possible types of task to generate mock data, `size` and `qps`:
- `size` (`/mock-data/segments/tasks?size=20`): the task will generate total number of `size` segments/logs and then finish.
- `qps` (`/mock-data/segments/tasks?qps=20`): the task will generate `qps` segments/logs per second continuously, until the task is [cancelled](#cancel-a-task).
Refer to [the segment template](segment-template.json), [the log template](logs-template.json) and the [Generators](#generators) for more details
about how to compose a template.
## Cancel a task
When the task is acknowledged by the server it will return a task id that can be used to cancelled
the task by sending a `DELETE` request to URL path `/mock-data/logs/tasks` with a parameter `requestId` (i.e.
`/mock-data/logs/tasks?requestId={request id returned in previous request}`):
```shell
curl -XDELETE 'http://localhost:12800/mock-data/segments/task?requestId=70d8a39e-b51e-49de-a6fc-43abf80482c1'
curl -XDELETE 'http://localhost:12800/mock-data/logs/task?requestId=70d8a39e-b51e-49de-a6fc-43abf80482c1'
```
## Cancel all tasks
When needed, you can also send a `DELETE` request to path `/mock-data/segments/tasks` to cancel all segment tasks.
```shell
curl -XDELETE 'http://localhost:12800/mock-data/segments/tasks
curl -XDELETE 'http://localhost:12800/mock-data/logs/tasks
```
## Generators
### `uuid`
`uuid` generator leverages `java.util.UUID` to generate a string. You can use `uuid` generator to fill the
`traceId` field of segments.
`changingFrequency` property can be used when you want to reuse a `uuid` for multiple times, for example,
if you want a `traceId` to be reused by 5 segments, then setting `changingFrequency` to `5` would do the trick.
By setting `changingFrequency` to `5`, `uuid` generates 1 string, and uses it for 5 times, then re-generates
a new uuid string and uses it for another 5 times.
```json
"traceId": {
"type": "uuid",
"changingFrequency": "5"
}
```
### `randomString` (`String`)
#### `length` (`int`)
`length` specifies the length of the random string to be generated,
i.e. `generatedString.length() == length` is always `true`.
#### `prefix` (`String`)
`prefix` is always added to the random strings **after** they are generated, that means:
- `generatedString.startsWith(prefix)` is always `true`, and,
- `generatedString.length() == length + prefix.length()` is always true.
#### `letters` (`boolean`)
Specifies whether the random string contains letters (i.e. `a-zA-Z`).
#### `numbers` (`boolean`)
Specifies whether the random string contains numbers (i.e. `0-9`).
#### `domainSize` (`int`)
When generating random strings, you might just want some random strings and use them over and over again randomly,
by setting `domainSize`, the generator generates `domainSize` random strings, and pick them randomly every time
you need a string.
### `randomBool` (`boolean`)
This generator generates a `Boolean` value, `true` or `false` with a default possibility of 50%, while you can change the `possibility` below.
#### `possibility` (`double`, `[0, 1]`)
`possibility` is a `double` value `>= 0` and `<= 1`, it's `0.5` by default, meaning **about** half of the generated values are `true`.
To always return a fixed boolean value `true`, you can just set the `possibility` to `1`, to always return a fixed boolean value `false`, you can set the `possibility` to `0`
```json
"error": {
"type": "randomBool",
"possibility": "0.9"
}
```
> 90 percent of the generated values are `true`.
### `randomInt` (`long`)
#### `min` (`long`)
The minimum value of the random integers, meaning all generated values satisfy `generatedInt >= min`.
#### `max` (`long`)
The maximum value of the random integers, meaning all generated values satisfy `generatedInt < min`.
#### `domainSize` (`int`)
This is similar to [`randomString`'s `domainSize`](#domainsize-int).
### `randomList` (`list` / `array`)
#### `size` (`int`)
The list size of the generated list, i.e. `generatedList.size() == size`.
#### `item` (`object`)
`item` is a template that will be use as a prototype to generate the list items, for example when generating a
list of `Tag`, the `item` should be the prototype of `Tag`, which can be composed by the generators again.
```json
"tags": {
"type": "randomList",
"size": 5,
"item": {
"key": {
"type": "randomString",
"length": "10",
"prefix": "test_tag_",
"letters": true,
"numbers": true,
"domainSize": 10
},
"value": {
"type": "randomString",
"length": "10",
"prefix": "test_value_",
"letters": true,
"numbers": true
}
}
}
```
### `fixedString` (`string`)
This generator always returns a fixed `value` of string.
### `sequence` (`long`)
`sequence` generator generates a sequence of monotonically increasing integers, with a configurable `fluctuation`.
#### `min` (`long`)
The minimum value of the sequence.
#### `max` (`long`)
The maximum value of the sequence.
#### `step` (`long`)
The increasing step of this sequence, i.e. `the next generated value == the previous value + step`.
#### `domainSize` (`int`)
This is similar to [`randomString`'s `domainSize`](#domainsize-int).
#### `fluctuation` (`int`)
By default, sequence is strictly increasing numbers, but in some cases you might want the numbers to fluctuate
slightly while they are increasing. Adding property `fluctuation` to the generator will add a random number
`>= -fluctuation, <= fluctuation` to the sequence elements.
For example, `min = 10, max = 15, step = 1` generates a sequence `[10, 11, 12, 13, 14, 15]`, but adding `fluctuation = 2` **might** generate a sequence `[10, 12, 11, 14, 13, 15]`.

View File

@ -0,0 +1,83 @@
{
"timestamp": {
"type": "sequence",
"min": "1649643929000",
"max": "1649653929000"
},
"serviceName": {
"type": "randomString",
"length": "20",
"prefix": "test_svc_name_",
"letters": true,
"numbers": true
},
"serviceInstanceName": {
"type": "randomString",
"length": "20",
"prefix": "test_svc_inst_name_",
"letters": true,
"numbers": true
},
"endpointName": {
"type": "randomString",
"length": "20",
"prefix": "test_endpoint_",
"letters": true,
"numbers": true
},
"traceId": {
"type": "randomString",
"length": "20",
"prefix": "test_trace_id_",
"letters": true,
"numbers": true
},
"traceSegmentId": {
"type": "randomString",
"length": "20",
"prefix": "test",
"letters": true,
"numbers": true
},
"spanId": {
"type": "randomInt",
"min": "0",
"max": "5"
},
"contentType": {
"type": "randomInt",
"min": 1,
"max": 1
},
"content": {
"type": "randomString",
"length": "10",
"prefix": "test",
"letters": true,
"numbers": true
},
"error": {
"type": "randomBool"
},
"tags": {
"type": "randomList",
"size": 5,
"item": {
"key": {
"type": "randomString",
"length": "10",
"prefix": "test",
"letters": true,
"numbers": true,
"domainSize": 10
},
"value": {
"type": "randomString",
"length": "10",
"prefix": "test",
"letters": true,
"numbers": true
}
}
}
}

View File

@ -0,0 +1,145 @@
{
"traceId": {
"type": "uuid",
"changingFrequency": "5"
},
"serviceInstanceName": {
"type": "randomString",
"length": "10",
"letters": true,
"numbers": true
},
"segmentId": {
"type": "randomString",
"length": "20",
"letters": true,
"numbers": true
},
"serviceName": {
"type": "randomString",
"length": "10",
"letters": true,
"numbers": true
},
"endpointName": {
"type": "randomString",
"length": "10",
"prefix": "test_",
"letters": true,
"numbers": true,
"domainSize": 10
},
"startTime": {
"type": "sequence",
"min": "1650510807000",
"max": "1650512807000"
},
"latency": {
"type": "randomInt",
"min": 100,
"max": 1000
},
"error": {
"type": "randomInt",
"min": 1,
"max": 1
},
"tags": {
"type": "randomList",
"size": 5,
"item": {
"key": {
"type": "randomString",
"length": "10",
"prefix": "test_tag_",
"letters": true,
"numbers": true,
"domainSize": 10
},
"value": {
"type": "randomString",
"length": "10",
"prefix": "test_value_",
"letters": true,
"numbers": true
}
}
},
"spans": {
"type": "randomList",
"size": 5,
"item": {
"spanId": {
"type": "sequence",
"min": "0",
"max": "5"
},
"parentSpanId": {
"type": "sequence",
"min": "-1",
"max": "4"
},
"startTime": {
"type": "randomInt",
"min": "1650510807000",
"max": "1650512807000",
"domainSize": 10
},
"endTime": {
"type": "randomInt",
"min": "1650510807000",
"max": "1650512807000",
"domainSize": 10
},
"operationName": {
"type": "randomString",
"length": "10",
"prefix": "test_endpoint_",
"letters": true,
"numbers": true
},
"peer": {
"type": "randomString",
"length": "10",
"prefix": "test_peer_",
"letters": true,
"numbers": true
},
"spanLayer": {
"type": "randomInt",
"min": "0",
"max": "4"
},
"componentId": {
"type": "randomInt",
"min": "0",
"max": "4"
},
"error": {
"type": "randomBool",
"possibility": "0.9"
},
"tags": {
"type": "randomList",
"size": 5,
"item": {
"key": {
"type": "randomString",
"length": "10",
"prefix": "test_tag_key_",
"letters": true,
"numbers": true,
"domainSize": 10
},
"value": {
"type": "randomString",
"length": "10",
"prefix": "test_tag_val_",
"letters": true,
"numbers": true
}
}
}
}
}
}

View File

@ -179,6 +179,8 @@ catalog:
path: "/en/setup/backend/backend-health-check"
- name: "CLI Setup"
path: "https://github.com/apache/skywalking-cli"
- name: "Mock Data Generator Setup"
path: "/en/setup/backend/backend-data-generator"
- name: "Contributing Guides"
catalog:
- name: "Contribute"
@ -237,7 +239,3 @@ catalog:
path: "/en/changes/changes-6.x"
- name: "5.x"
path: "/en/changes/changes-5.x"

View File

@ -22,10 +22,12 @@ import java.util.ArrayList;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SEGMENT;
@ToString
@ScopeDeclaration(id = SEGMENT, name = "Segment")
public class Segment extends Source {

View File

@ -60,7 +60,7 @@ public class HTTPServer implements Server {
.http1MaxHeaderSize(config.getMaxRequestHeaderSize())
.idleTimeout(Duration.ofMillis(config.getIdleTimeOut()))
.decorator(Route.ofCatchAll(), (delegate, ctx, req) -> {
if (!this.allowedMethods.contains(ctx.method())) {
if (!allowedMethods.contains(ctx.method())) {
return HttpResponse.of(HttpStatus.METHOD_NOT_ALLOWED);
}
return delegate.serve(ctx, req);

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
~ 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">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>server-tools</artifactId>
<groupId>org.apache.skywalking</groupId>
<version>9.1.0-SNAPSHOT</version>
</parent>
<artifactId>data-generator</artifactId>
<name>data-generator</name>
<description>
Module to generate data for testing.
</description>
<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>server-starter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>application.yml</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,49 @@
#!/usr/bin/env sh
# 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.
PRG="$0"
PRGDIR=$(dirname "$PRG")
[ -z "$OAP_HOME" ] && OAP_HOME=$(cd "$PRGDIR/../../.." > /dev/null || exit 1; pwd)
OAP_LOG_DIR="${OAP_LOG_DIR:-${OAP_HOME}/logs}"
JAVA_OPTS="${JAVA_OPTS:- -Xms256M -Xmx512M}"
if [ ! -d "${OAP_LOG_DIR}" ]; then
mkdir -p "${OAP_LOG_DIR}"
fi
_RUNJAVA=${JAVA_HOME}/bin/java
[ -z "$JAVA_HOME" ] && _RUNJAVA=java
CLASSPATH="$OAP_HOME/tools/data-generator/config:$OAP_HOME/config:$CLASSPATH"
for i in "$OAP_HOME"/oap-libs/*.jar
do
CLASSPATH="$i:$CLASSPATH"
done
OAP_OPTIONS=" -Doap.logDir=${OAP_LOG_DIR}"
eval exec "\"$_RUNJAVA\" ${JAVA_OPTS} ${OAP_OPTIONS} -classpath $CLASSPATH org.apache.skywalking.starter.DataGeneratorStartUp \
2>${OAP_LOG_DIR}/oap.log 1> /dev/null &"
if [ $? -eq 0 ]; then
sleep 1
echo "SkyWalking OAP started successfully!"
else
echo "SkyWalking OAP started failure!"
exit 1
fi

View File

@ -0,0 +1,54 @@
/*
* 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.generator;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Data;
@JsonDeserialize(builder = BoolGenerator.Builder.class)
public final class BoolGenerator implements Generator<Boolean> {
private final Random random = ThreadLocalRandom.current();
private final double possibility;
public BoolGenerator(Builder builder) {
possibility = builder.possibility;
}
@Override
public Boolean next() {
return random.nextDouble() < possibility;
}
@Override
public String toString() {
return String.valueOf(next());
}
@Data
public static class Builder {
private double possibility = .5;
public BoolGenerator build() {
return new BoolGenerator(this);
}
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.generator;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Data;
@JsonDeserialize(builder = FixedStringGenerator.Builder.class)
public final class FixedStringGenerator implements Generator<String> {
private final String value;
public FixedStringGenerator(Builder builder) {
value = builder.value;
}
@Override
public String next() {
return value;
}
@Data
public static class Builder {
private String value;
public FixedStringGenerator build() {
return new FixedStringGenerator(this);
}
}
@Override
public String toString() {
return String.valueOf(next());
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.generator;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@Type(value = StringGenerator.class, name = "randomString"),
@Type(value = BoolGenerator.class, name = "randomBool"),
@Type(value = IntGenerator.class, name = "randomInt"),
@Type(value = ListGenerator.class, name = "randomList"),
@Type(value = FixedStringGenerator.class, name = "fixedString"),
@Type(value = SequenceGenerator.class, name = "sequence"),
@Type(value = UUIDGenerator.class, name = "uuid"),
})
public interface Generator<T> {
public T next();
default public void reset() {
}
}

View File

@ -0,0 +1,102 @@
/*
* 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.generator;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Preconditions;
import lombok.Data;
@JsonDeserialize(builder = IntGenerator.Builder.class)
public final class IntGenerator implements Generator<Long> {
private final boolean limitedDomain;
private final Long min;
private final Long max;
private final Integer domainSize;
private final ThreadLocalRandom random = ThreadLocalRandom.current();
private final Set<Long> domain = new HashSet<>();
public IntGenerator(Builder builder) {
min = builder.min;
max = builder.max;
domainSize = builder.domainSize;
limitedDomain = builder.domainSize != null && builder.domainSize > 0;
reset();
}
@Override
public Long next() {
if (!limitedDomain) {
return next0();
}
return domain
.stream()
.skip(random.nextInt(domain.size()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Should never happen"));
}
@Override
public void reset() {
if (limitedDomain) {
domain.clear();
while (domain.size() < domainSize) {
domain.add(next0());
}
}
}
private long next0() {
if (min != null && max != null) {
return random.nextLong(max - min + 1) + min; // Might overflow, but it's not worthy to check
}
if (min != null) {
return Math.abs(random.nextLong()) + min;
}
return random.nextLong(max);
}
@Override
public String toString() {
return String.valueOf(next());
}
@Data
public static class Builder {
private Long min;
private Long max;
private Integer domainSize;
public IntGenerator build() {
if (min != null && max != null) {
Preconditions.checkArgument(min <= max, "min must be <= max");
if (domainSize != null) {
Preconditions.checkArgument(domainSize <= max - min,
"domain size must be <= max - min");
}
}
return new IntGenerator(this);
}
}
}

View File

@ -0,0 +1,60 @@
/*
* 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.generator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Data;
@JsonDeserialize(builder = ListGenerator.Builder.class)
public final class ListGenerator<T> implements Generator<List<T>> {
private final T item;
private final int size;
public ListGenerator(Builder<T> builder) {
item = builder.item;
size = builder.size;
}
@Override
public List<T> next() {
return IntStream
.range(0, size)
.mapToObj($ -> item)
.collect(Collectors.toList());
}
@Override
public void reset() {
((Generator<?>) item).reset();
}
@Data
public static class Builder<T> {
private int size;
private T item;
public ListGenerator<T> build() {
return new ListGenerator<>(this);
}
}
}

View File

@ -0,0 +1,118 @@
/*
* 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.generator;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Preconditions;
import lombok.Data;
import lombok.experimental.Accessors;
@JsonDeserialize(builder = SequenceGenerator.Builder.class)
public final class SequenceGenerator implements Generator<Long> {
private final boolean limitedDomain;
private final long min;
private final long max;
private final long step;
private final Integer fluctuation;
private final Integer domainSize;
private final Random random = ThreadLocalRandom.current();
private final Set<Long> domain = new HashSet<>();
private volatile Long last;
public SequenceGenerator(Builder builder) {
min = builder.min;
max = builder.max;
step = builder.step;
fluctuation = builder.fluctuation;
domainSize = builder.domainSize;
limitedDomain = builder.domainSize != null && builder.domainSize > 0;
reset();
}
@Override
public Long next() {
if (!limitedDomain) {
return next0();
}
return domain
.stream()
.skip(random.nextInt(domain.size()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Should never happen"));
}
private synchronized long next0() {
long next = last == null ? min : last + step;
if (fluctuation != null) {
int j = random.nextInt(fluctuation);
next += random.nextBoolean() ? j : -j;
}
if (next > max) {
return max;
}
if (next < min) {
return min;
}
return last = next;
}
@Override
public void reset() {
last = null;
if (limitedDomain) {
domain.clear();
while (domain.size() < domainSize) {
domain.add(next0());
}
}
}
@Override
public String toString() {
return String.valueOf(next());
}
@Data
@Accessors(chain = true)
public static class Builder {
private long min = Long.MIN_VALUE;
private long max = Long.MAX_VALUE;
private long step = 1;
private Integer domainSize;
private Integer fluctuation;
public SequenceGenerator build() {
if (domainSize != null) {
Preconditions.checkArgument(domainSize > 0, "domainSize must be > 0");
Preconditions.checkArgument(domainSize + min <= max,
"domain size must be <= max - min");
}
return new SequenceGenerator(this);
}
}
}

View File

@ -0,0 +1,90 @@
/*
* 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.generator;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.google.common.base.Strings;
import org.apache.commons.lang3.RandomStringUtils;
import lombok.Data;
@JsonDeserialize(builder = StringGenerator.Builder.class)
public final class StringGenerator implements Generator<String> {
private final int length;
private final String prefix;
private final boolean letters;
private final boolean numbers;
private final boolean limitedDomain;
private final Random random = ThreadLocalRandom.current();
private final Set<String> domain = new HashSet<>();
public StringGenerator(Builder builder) {
length = builder.length;
prefix = builder.prefix;
letters = builder.letters;
numbers = builder.numbers;
limitedDomain = builder.domainSize > 0;
if (limitedDomain) {
while (domain.size() < builder.domainSize) {
final String r = RandomStringUtils.random(length, letters, numbers);
if (!Strings.isNullOrEmpty(builder.prefix)) {
domain.add(builder.prefix + r);
} else {
domain.add(r);
}
}
}
}
@Override
public String next() {
if (!limitedDomain) {
return Strings.nullToEmpty(prefix)
+ RandomStringUtils.random(length, letters, numbers);
}
return domain
.stream()
.skip(random.nextInt(domain.size()))
.findFirst()
.orElseThrow(() -> new RuntimeException("Should never happen"));
}
@Override
public String toString() {
return String.valueOf(next());
}
@Data
public static class Builder {
private int length;
private String prefix;
private boolean letters;
private boolean numbers;
private int domainSize;
public StringGenerator build() {
return new StringGenerator(this);
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.skywalking.generator;
import static com.google.common.base.Preconditions.checkArgument;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Data;
@JsonDeserialize(builder = UUIDGenerator.Builder.class)
public final class UUIDGenerator implements Generator<String> {
private final int changingFrequency;
private final AtomicInteger counter;
private final AtomicReference<String> last =
new AtomicReference<>(UUID.randomUUID().toString());
public UUIDGenerator(Builder builder) {
checkArgument(builder.changingFrequency > 0, "changingFrequency must be greater than 0");
changingFrequency = builder.changingFrequency;
counter = new AtomicInteger();
reset();
}
@Override
public String next() {
if (counter.incrementAndGet() < changingFrequency) {
return last.get();
}
reset();
return last.getAndSet(UUID.randomUUID().toString());
}
@Override
public String toString() {
return String.valueOf(next());
}
@Override
public void reset() {
counter.set(0);
}
@Data
public static class Builder {
private int changingFrequency = 1;
public UUIDGenerator build() {
return new UUIDGenerator(this);
}
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.module;
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
public class DataGeneratorModule extends ModuleDefine {
public static final String NAME = "data-generator";
public DataGeneratorModule() {
super(NAME);
}
@Override
public Class<?>[] services() {
return new Class[0];
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.module;
import java.util.Arrays;
import java.util.List;
import com.linecorp.armeria.common.HttpMethod;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.server.HTTPHandlerRegister;
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.restapi.LogGeneratorHandler;
import org.apache.skywalking.restapi.SegmentGeneratorHandler;
public class DataGeneratorModuleProvider extends ModuleProvider {
@Override
public String name() {
return "default";
}
@Override
public Class<? extends ModuleDefine> module() {
return DataGeneratorModule.class;
}
@Override
public ModuleConfig createConfigBeanIfAbsent() {
return null;
}
@Override
public void prepare() throws ServiceNotProvidedException, ModuleStartException {
}
@Override
public void start() throws ServiceNotProvidedException, ModuleStartException {
final List<HttpMethod> methods = Arrays.asList(
HttpMethod.GET,
HttpMethod.POST,
HttpMethod.DELETE
);
final HTTPHandlerRegister register =
getManager()
.find(CoreModule.NAME)
.provider()
.getService(HTTPHandlerRegister.class);
register.addHandler(new SegmentGeneratorHandler(getManager()), methods);
register.addHandler(new LogGeneratorHandler(getManager()), methods);
}
@Override
public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException {
}
@Override
public String[] requiredModules() {
return new String[0];
}
}

View File

@ -0,0 +1,133 @@
/*
* 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.restapi;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.HttpStatus;
import com.linecorp.armeria.common.MediaType;
import com.linecorp.armeria.common.util.EventLoopGroups;
import com.linecorp.armeria.server.annotation.Default;
import com.linecorp.armeria.server.annotation.Delete;
import com.linecorp.armeria.server.annotation.Get;
import com.linecorp.armeria.server.annotation.Param;
import com.linecorp.armeria.server.annotation.Post;
import com.linecorp.armeria.server.annotation.ProducesJson;
import com.linecorp.armeria.server.annotation.RequestObject;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.source.Log;
import org.apache.skywalking.oap.server.core.source.SourceReceiver;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import io.netty.channel.EventLoopGroup;
import io.netty.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LogGeneratorHandler {
private final SourceReceiver sourceReceiver;
private final Map<String, Future<?>> futures = new ConcurrentHashMap<>();
private final EventLoopGroup eventLoopGroup = EventLoopGroups.newEventLoopGroup(10);
public LogGeneratorHandler(ModuleManager manager) {
sourceReceiver = manager.find(CoreModule.NAME).provider().getService(SourceReceiver.class);
}
@Post("/mock-data/logs/tasks")
public HttpResponse generateMockLogs(
@Default("0") @Param("size") int size,
@Default("0") @Param("qps") int qps,
@RequestObject LogRequest request) {
if (size > 0 && qps > 0) {
return HttpResponse.of(
HttpStatus.BAD_REQUEST,
MediaType.PLAIN_TEXT,
"size and qps can't be both set");
}
log.info("Generate {} mock logs, qps: {}, template: {}", size, qps, request);
final IntConsumer generator = unused -> {
final Log l = request.next();
log.debug("Generating log: {}", l);
sourceReceiver.receive(l);
};
final String requestId = UUID.randomUUID().toString();
final Future<?> future;
if (size > 0) {
future = eventLoopGroup.submit(() -> IntStream
.range(0, size)
.forEach(generator));
} else {
future = eventLoopGroup.scheduleAtFixedRate(() -> IntStream
.range(0, qps)
.forEach(generator), 0, 1, TimeUnit.SECONDS);
}
futures.put(requestId, future);
future.addListener(f -> {
if (f.isDone()) {
futures.remove(requestId);
log.info("Generate mock logs finished: {}, requestId: {}", f.isSuccess(),
requestId);
}
if (f.cause() != null) {
log.error(f.cause().getMessage(), f.cause());
}
});
return HttpResponse.of(MediaType.PLAIN_TEXT, requestId);
}
@Delete("/mock-data/logs/task")
public HttpResponse cancelRequest(@Param("requestId") String requestId) {
final Future<?> future = futures.get(requestId);
if (future == null) {
return HttpResponse.of(
HttpStatus.NOT_FOUND,
MediaType.PLAIN_TEXT_UTF_8,
"No such request: %s", requestId);
}
log.info("Cancelling request: {}", requestId);
future.cancel(true);
return HttpResponse.of(HttpStatus.OK);
}
@Delete("/mock-data/logs/tasks")
public HttpResponse cancelAllRequests() {
futures.forEach((t, u) -> {
log.info("Cancelling request: {}", t);
u.cancel(true);
});
return HttpResponse.of(HttpStatus.OK);
}
@ProducesJson
@Get("/mock-data/logs/tasks")
public Set<String> listRequest() {
return futures.keySet();
}
}

View File

@ -0,0 +1,105 @@
/*
* 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.restapi;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
import org.apache.skywalking.apm.network.logging.v3.LogTags;
import org.apache.skywalking.generator.Generator;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag;
import org.apache.skywalking.oap.server.core.query.type.ContentType;
import org.apache.skywalking.oap.server.core.source.Log;
import lombok.Data;
import lombok.SneakyThrows;
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public final class LogRequest implements Generator<Log> {
@JsonIgnore
private final ObjectMapper om = new ObjectMapper();
private Generator<Long> timestamp;
private Generator<String> serviceName;
private Generator<String> serviceInstanceName;
private Generator<String> endpointName;
private Generator<String> traceId;
private Generator<String> traceSegmentId;
private Generator<Long> spanId;
private Generator<Long> contentType;
private Generator<String> content;
private Generator<List<TagGenerator>> tags;
private Generator<Boolean> error;
@SneakyThrows
@Override
public Log next() {
final Log log = new Log();
log.setTimestamp(getTimestamp().next());
log.setServiceId(
IDManager.ServiceID.buildId(
getServiceName().next(),
true));
log.setServiceInstanceId(
IDManager.ServiceInstanceID.buildId(
log.getServiceId(),
getServiceInstanceName().next()));
log.setEndpointId(
IDManager.EndpointID.buildId(
log.getServiceId(),
getEndpointName().next()));
log.setTraceId(getTraceId().next());
log.setTraceSegmentId(getTraceSegmentId().next());
log.setSpanId(getSpanId().next().intValue());
log.setContentType(ContentType.instanceOf(getContentType().next().intValue()));
log.setContent(getContent().next());
log.setError(getError().next());
log.setTimeBucket(TimeBucket.getRecordTimeBucket(log.getTimestamp()));
log.setTags(
getTags()
.next()
.stream()
.map(TagGenerator::next)
.collect(Collectors.<Tag>toList()));
log.setTagsRawData(
LogTags
.newBuilder()
.addAllData(
log
.getTags()
.stream()
.map(it -> KeyStringValuePair
.newBuilder()
.setKey(it.getKey())
.setValue(it.getValue())
.build())
.collect(Collectors.toList()))
.build()
.toByteArray());
log.setUniqueId(UUID.randomUUID().toString());
return log;
}
}

View File

@ -0,0 +1,134 @@
/*
* 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.restapi;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.common.HttpStatus;
import com.linecorp.armeria.common.MediaType;
import com.linecorp.armeria.common.util.EventLoopGroups;
import com.linecorp.armeria.server.annotation.Default;
import com.linecorp.armeria.server.annotation.Delete;
import com.linecorp.armeria.server.annotation.Get;
import com.linecorp.armeria.server.annotation.Param;
import com.linecorp.armeria.server.annotation.Post;
import com.linecorp.armeria.server.annotation.ProducesJson;
import com.linecorp.armeria.server.annotation.RequestObject;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.source.Segment;
import org.apache.skywalking.oap.server.core.source.SourceReceiver;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import io.netty.channel.EventLoopGroup;
import io.netty.util.concurrent.Future;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SegmentGeneratorHandler {
private final SourceReceiver sourceReceiver;
private final Map<String, Future<?>> futures = new ConcurrentHashMap<>();
private final EventLoopGroup eventLoopGroup = EventLoopGroups.newEventLoopGroup(10);
public SegmentGeneratorHandler(ModuleManager manager) {
sourceReceiver = manager.find(CoreModule.NAME).provider().getService(SourceReceiver.class);
}
@Post("/mock-data/segments/tasks")
public HttpResponse generateMockSegments(
@Default("0") @Param("size") int size,
@Default("0") @Param("qps") int qps,
@RequestObject SegmentRequest request) {
if (size > 0 && qps > 0) {
return HttpResponse.of(
HttpStatus.BAD_REQUEST,
MediaType.PLAIN_TEXT,
"size and qps can't be both set");
}
log.info("Generate {} mock segments, qps: {}, template: {}", size, qps, request);
final IntConsumer generator = unused -> {
final Segment segment = request.next();
log.debug("Generating segment: {}", segment);
sourceReceiver.receive(segment);
};
final String requestId = UUID.randomUUID().toString();
final Future<?> future;
if (size > 0) {
future = eventLoopGroup.submit(() -> IntStream
.range(0, size)
.forEach(generator));
} else {
future = eventLoopGroup.scheduleAtFixedRate(() -> IntStream
.range(0, qps)
.forEach(generator), 0, 1, TimeUnit.SECONDS);
}
futures.put(requestId, future);
future.addListener(f -> {
if (f.isDone()) {
futures.remove(requestId);
log.info("Generate mock segments finished: {}, requestId: {}", f.isSuccess(),
requestId);
}
if (f.cause() != null && !(f.cause() instanceof CancellationException)) {
log.error("Exception in future: ", f.cause());
}
});
return HttpResponse.of(MediaType.PLAIN_TEXT, requestId);
}
@Delete("/mock-data/segments/task")
public HttpResponse cancelRequest(@Param("requestId") String requestId) {
final Future<?> future = futures.get(requestId);
if (future == null) {
return HttpResponse.of(
HttpStatus.NOT_FOUND,
MediaType.PLAIN_TEXT_UTF_8,
"No such request: %s", requestId);
}
log.info("Cancelling request: {}", requestId);
future.cancel(true);
return HttpResponse.of(HttpStatus.OK);
}
@Delete("/mock-data/segments/tasks")
public HttpResponse cancelAllRequests() {
futures.forEach((t, u) -> {
log.info("Cancelling request: {}", t);
u.cancel(true);
});
return HttpResponse.of(HttpStatus.OK);
}
@ProducesJson
@Get("/mock-data/segments/tasks")
public Set<String> listRequest() {
return futures.keySet();
}
}

View File

@ -0,0 +1,100 @@
/*
* 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.restapi;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject;
import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
import org.apache.skywalking.generator.Generator;
import org.apache.skywalking.oap.server.core.analysis.IDManager;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag;
import org.apache.skywalking.oap.server.core.source.Segment;
import lombok.Data;
@Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public final class SegmentRequest implements Generator<Segment> {
private Generator<String> segmentId;
private Generator<String> traceId;
private Generator<String> serviceName;
private Generator<String> serviceInstanceName;
private Generator<String> endpointName;
private Generator<Long> startTime;
private Generator<Long> latency;
private Generator<Long> error;
private Generator<List<TagGenerator>> tags;
private Generator<List<SpanGenerator>> spans;
@Override
public Segment next() {
final String traceId = getTraceId().next();
final String serviceName = getServiceName().next();
final String serviceInstanceName = getServiceInstanceName().next();
final String endpointName = getEndpointName().next();
final String segmentId = getSegmentId().next();
final SegmentObject segmentObj = SegmentObject
.newBuilder()
.setTraceId(traceId)
.setTraceSegmentId(segmentId)
.addAllSpans(
getSpans()
.next()
.stream()
.map(SpanGenerator::next)
.collect(Collectors.<SpanObject>toList()))
.setService(serviceName)
.setServiceInstance(serviceInstanceName)
.build();
// Reset the span generator to generate the span id from 0
getSpans().reset();
final Segment segment = new Segment();
segment.setSegmentId(segmentId);
segment.setTraceId(traceId);
segment.setServiceId(
IDManager.ServiceID.buildId(serviceName, true));
segment.setServiceInstanceId(
IDManager.ServiceInstanceID.buildId(
segment.getServiceId(),
serviceInstanceName));
segment.setEndpointId(
IDManager.EndpointID.buildId(
segment.getServiceId(),
endpointName));
segment.setStartTime(getStartTime().next());
segment.setLatency(getLatency().next().intValue());
segment.setIsError(getError().next().intValue());
segment.setTimeBucket(TimeBucket.getRecordTimeBucket(segment.getStartTime()));
segment.setTags(
getTags()
.next()
.stream()
.map(TagGenerator::next)
.collect(Collectors.<Tag>toList()));
segment.setDataBinary(segmentObj.toByteArray());
return segment;
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.restapi;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.apache.skywalking.apm.network.common.v3.KeyStringValuePair;
import org.apache.skywalking.apm.network.language.agent.v3.SpanLayer;
import org.apache.skywalking.apm.network.language.agent.v3.SpanObject;
import org.apache.skywalking.generator.Generator;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public final class SpanGenerator implements Generator<SpanObject> {
private Generator<Long> spanId;
private Generator<Long> parentSpanId;
private Generator<Long> startTime;
private Generator<Long> endTime;
private Generator<String> operationName;
private Generator<String> peer;
private Generator<Long> spanLayer;
private Generator<Long> componentId;
private Generator<Boolean> error;
private Generator<List<TagGenerator>> tags;
@Override
public SpanObject next() {
return SpanObject
.newBuilder()
.setSpanId(getSpanId().next().intValue())
.setParentSpanId(getParentSpanId().next().intValue())
.setStartTime(getStartTime().next())
.setEndTime(getEndTime().next())
.setOperationName(getOperationName().next())
.setPeer(getPeer().next())
.setSpanLayer(SpanLayer.forNumber(getSpanLayer().next().intValue()))
.setComponentId(getComponentId().next().intValue())
.setIsError(getError().next())
.addAllTags(
getTags()
.next()
.stream()
.map(TagGenerator::next)
.map(it -> KeyStringValuePair
.newBuilder().setKey(it.getKey())
.setValue(it.getValue()).build())
.collect(Collectors.toList()))
.build();
}
@Override
public void reset() {
spanId.reset();
parentSpanId.reset();
startTime.reset();
endTime.reset();
operationName.reset();
peer.reset();
spanLayer.reset();
componentId.reset();
error.reset();
tags.reset();
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.restapi;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import org.apache.skywalking.generator.Generator;
import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public final class TagGenerator implements Generator<Tag> {
private Generator<String> key;
private Generator<String> value;
@Override
public Tag next() {
return new Tag(key.next(), value.next());
}
@Override
public void reset() {
key.reset();
value.reset();
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.starter;
import org.apache.skywalking.oap.server.starter.OAPServerBootstrap;
public class DataGeneratorStartUp {
public static void main(String[] args) {
OAPServerBootstrap.start();
}
}

View File

@ -0,0 +1,19 @@
#
# 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.module.DataGeneratorModule

View File

@ -0,0 +1,19 @@
#
# 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.module.DataGeneratorModuleProvider

View File

@ -0,0 +1,179 @@
# 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.
cluster:
selector: ${SW_CLUSTER:standalone}
standalone:
core:
selector: ${SW_CORE:default}
default:
# Mixed: Receive agent data, Level 1 aggregate, Level 2 aggregate
# Receiver: Receive agent data, Level 1 aggregate
# Aggregator: Level 2 aggregate
role: ${SW_CORE_ROLE:Mixed} # Mixed/Receiver/Aggregator
restHost: ${SW_CORE_REST_HOST:0.0.0.0}
restPort: ${SW_CORE_REST_PORT:12800}
restContextPath: ${SW_CORE_REST_CONTEXT_PATH:/}
restMinThreads: ${SW_CORE_REST_JETTY_MIN_THREADS:1}
restMaxThreads: ${SW_CORE_REST_JETTY_MAX_THREADS:200}
restIdleTimeOut: ${SW_CORE_REST_JETTY_IDLE_TIMEOUT:30000}
restAcceptorPriorityDelta: ${SW_CORE_REST_JETTY_DELTA:0}
restAcceptQueueSize: ${SW_CORE_REST_JETTY_QUEUE_SIZE:0}
httpMaxRequestHeaderSize: ${SW_CORE_HTTP_MAX_REQUEST_HEADER_SIZE:8192}
gRPCHost: ${SW_CORE_GRPC_HOST:0.0.0.0}
gRPCPort: ${SW_CORE_GRPC_PORT:11800}
maxConcurrentCallsPerConnection: ${SW_CORE_GRPC_MAX_CONCURRENT_CALL:0}
maxMessageSize: ${SW_CORE_GRPC_MAX_MESSAGE_SIZE:0}
gRPCThreadPoolQueueSize: ${SW_CORE_GRPC_POOL_QUEUE_SIZE:-1}
gRPCThreadPoolSize: ${SW_CORE_GRPC_THREAD_POOL_SIZE:-1}
gRPCSslEnabled: ${SW_CORE_GRPC_SSL_ENABLED:false}
gRPCSslKeyPath: ${SW_CORE_GRPC_SSL_KEY_PATH:""}
gRPCSslCertChainPath: ${SW_CORE_GRPC_SSL_CERT_CHAIN_PATH:""}
gRPCSslTrustedCAPath: ${SW_CORE_GRPC_SSL_TRUSTED_CA_PATH:""}
downsampling:
- Hour
- Day
# Set a timeout on metrics data. After the timeout has expired, the metrics data will automatically be deleted.
enableDataKeeperExecutor: ${SW_CORE_ENABLE_DATA_KEEPER_EXECUTOR:true} # Turn it off then automatically metrics data delete will be close.
dataKeeperExecutePeriod: ${SW_CORE_DATA_KEEPER_EXECUTE_PERIOD:5} # How often the data keeper executor runs periodically, unit is minute
recordDataTTL: ${SW_CORE_RECORD_DATA_TTL:3} # Unit is day
metricsDataTTL: ${SW_CORE_METRICS_DATA_TTL:7} # Unit is day
# The period of L1 aggregation flush to L2 aggregation. Unit is ms.
l1FlushPeriod: ${SW_CORE_L1_AGGREGATION_FLUSH_PERIOD:500}
# The threshold of session time. Unit is ms. Default value is 70s.
storageSessionTimeout: ${SW_CORE_STORAGE_SESSION_TIMEOUT:70000}
# The period of doing data persistence. Unit is second.Default value is 25s
persistentPeriod: ${SW_CORE_PERSISTENT_PERIOD:25}
# Cache metrics data for 1 minute to reduce database queries, and if the OAP cluster changes within that minute,
# the metrics may not be accurate within that minute.
enableDatabaseSession: ${SW_CORE_ENABLE_DATABASE_SESSION:true}
topNReportPeriod: ${SW_CORE_TOPN_REPORT_PERIOD:10} # top_n record worker report cycle, unit is minute
# Extra model column are the column defined by in the codes, These columns of model are not required logically in aggregation or further query,
# and it will cause more load for memory, network of OAP and storage.
# But, being activated, user could see the name in the storage entities, which make users easier to use 3rd party tool, such as Kibana->ES, to query the data by themselves.
activeExtraModelColumns: ${SW_CORE_ACTIVE_EXTRA_MODEL_COLUMNS:false}
# The max length of service + instance names should be less than 200
serviceNameMaxLength: ${SW_SERVICE_NAME_MAX_LENGTH:70}
instanceNameMaxLength: ${SW_INSTANCE_NAME_MAX_LENGTH:70}
# The max length of service + endpoint names should be less than 240
endpointNameMaxLength: ${SW_ENDPOINT_NAME_MAX_LENGTH:150}
# Define the set of span tag keys, which should be searchable through the GraphQL.
searchableTracesTags: ${SW_SEARCHABLE_TAG_KEYS:http.method,status_code,db.type,db.instance,mq.queue,mq.topic,mq.broker}
# Define the set of log tag keys, which should be searchable through the GraphQL.
searchableLogsTags: ${SW_SEARCHABLE_LOGS_TAG_KEYS:level}
# Define the set of alarm tag keys, which should be searchable through the GraphQL.
searchableAlarmTags: ${SW_SEARCHABLE_ALARM_TAG_KEYS:level}
# The number of threads used to prepare metrics data to the storage.
prepareThreads: ${SW_CORE_PREPARE_THREADS:2}
# Turn it on then automatically grouping endpoint by the given OpenAPI definitions.
enableEndpointNameGroupingByOpenapi: ${SW_CORE_ENABLE_ENDPOINT_NAME_GROUPING_BY_OPAENAPI:true}
storage:
selector: ${SW_STORAGE:h2}
elasticsearch:
namespace: ${SW_NAMESPACE:""}
clusterNodes: ${SW_STORAGE_ES_CLUSTER_NODES:localhost:9200}
protocol: ${SW_STORAGE_ES_HTTP_PROTOCOL:"http"}
connectTimeout: ${SW_STORAGE_ES_CONNECT_TIMEOUT:3000}
socketTimeout: ${SW_STORAGE_ES_SOCKET_TIMEOUT:30000}
responseTimeout: ${SW_STORAGE_ES_RESPONSE_TIMEOUT:15000}
numHttpClientThread: ${SW_STORAGE_ES_NUM_HTTP_CLIENT_THREAD:0}
user: ${SW_ES_USER:""}
password: ${SW_ES_PASSWORD:""}
trustStorePath: ${SW_STORAGE_ES_SSL_JKS_PATH:""}
trustStorePass: ${SW_STORAGE_ES_SSL_JKS_PASS:""}
secretsManagementFile: ${SW_ES_SECRETS_MANAGEMENT_FILE:""} # Secrets management file in the properties format includes the username, password, which are managed by 3rd party tool.
dayStep: ${SW_STORAGE_DAY_STEP:1} # Represent the number of days in the one minute/hour/day index.
indexShardsNumber: ${SW_STORAGE_ES_INDEX_SHARDS_NUMBER:1} # Shard number of new indexes
indexReplicasNumber: ${SW_STORAGE_ES_INDEX_REPLICAS_NUMBER:1} # Replicas number of new indexes
# Super data set has been defined in the codes, such as trace segments.The following 3 config would be improve es performance when storage super size data in es.
superDatasetDayStep: ${SW_SUPERDATASET_STORAGE_DAY_STEP:-1} # Represent the number of days in the super size dataset record index, the default value is the same as dayStep when the value is less than 0
superDatasetIndexShardsFactor: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_SHARDS_FACTOR:5} # This factor provides more shards for the super data set, shards number = indexShardsNumber * superDatasetIndexShardsFactor. Also, this factor effects Zipkin and Jaeger traces.
superDatasetIndexReplicasNumber: ${SW_STORAGE_ES_SUPER_DATASET_INDEX_REPLICAS_NUMBER:0} # Represent the replicas number in the super size dataset record index, the default value is 0.
indexTemplateOrder: ${SW_STORAGE_ES_INDEX_TEMPLATE_ORDER:0} # the order of index template
bulkActions: ${SW_STORAGE_ES_BULK_ACTIONS:5000} # Execute the async bulk record data every ${SW_STORAGE_ES_BULK_ACTIONS} requests
# flush the bulk every 10 seconds whatever the number of requests
# INT(flushInterval * 2/3) would be used for index refresh period.
flushInterval: ${SW_STORAGE_ES_FLUSH_INTERVAL:15}
concurrentRequests: ${SW_STORAGE_ES_CONCURRENT_REQUESTS:2} # the number of concurrent requests
resultWindowMaxSize: ${SW_STORAGE_ES_QUERY_MAX_WINDOW_SIZE:10000}
metadataQueryMaxSize: ${SW_STORAGE_ES_QUERY_MAX_SIZE:5000}
segmentQueryMaxSize: ${SW_STORAGE_ES_QUERY_SEGMENT_SIZE:200}
profileTaskQueryMaxSize: ${SW_STORAGE_ES_QUERY_PROFILE_TASK_SIZE:200}
oapAnalyzer: ${SW_STORAGE_ES_OAP_ANALYZER:"{\"analyzer\":{\"oap_analyzer\":{\"type\":\"stop\"}}}"} # the oap analyzer.
oapLogAnalyzer: ${SW_STORAGE_ES_OAP_LOG_ANALYZER:"{\"analyzer\":{\"oap_log_analyzer\":{\"type\":\"standard\"}}}"} # the oap log analyzer. It could be customized by the ES analyzer configuration to support more language log formats, such as Chinese log, Japanese log and etc.
advanced: ${SW_STORAGE_ES_ADVANCED:""}
h2:
driver: ${SW_STORAGE_H2_DRIVER:org.h2.jdbcx.JdbcDataSource}
url: ${SW_STORAGE_H2_URL:jdbc:h2:mem:skywalking-oap-db;DB_CLOSE_DELAY=-1}
user: ${SW_STORAGE_H2_USER:sa}
metadataQueryMaxSize: ${SW_STORAGE_H2_QUERY_MAX_SIZE:5000}
maxSizeOfArrayColumn: ${SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN:20}
numOfSearchableValuesPerTag: ${SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG:2}
maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:100}
asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:1}
agent-analyzer:
selector: ${SW_AGENT_ANALYZER:default}
default:
# The default sampling rate and the default trace latency time configured by the 'traceSamplingPolicySettingsFile' file.
traceSamplingPolicySettingsFile: ${SW_TRACE_SAMPLING_POLICY_SETTINGS_FILE:trace-sampling-policy-settings.yml}
slowDBAccessThreshold: ${SW_SLOW_DB_THRESHOLD:default:200,mongodb:100} # The slow database access thresholds. Unit ms.
forceSampleErrorSegment: ${SW_FORCE_SAMPLE_ERROR_SEGMENT:true} # When sampling mechanism active, this config can open(true) force save some error segment. true is default.
segmentStatusAnalysisStrategy: ${SW_SEGMENT_STATUS_ANALYSIS_STRATEGY:FROM_SPAN_STATUS} # Determine the final segment status from the status of spans. Available values are `FROM_SPAN_STATUS` , `FROM_ENTRY_SPAN` and `FROM_FIRST_SPAN`. `FROM_SPAN_STATUS` represents the segment status would be error if any span is in error status. `FROM_ENTRY_SPAN` means the segment status would be determined by the status of entry spans only. `FROM_FIRST_SPAN` means the segment status would be determined by the status of the first span only.
# Nginx and Envoy agents can't get the real remote address.
# Exit spans with the component in the list would not generate the client-side instance relation metrics.
noUpstreamRealAddressAgents: ${SW_NO_UPSTREAM_REAL_ADDRESS:6000,9000}
meterAnalyzerActiveFiles: ${SW_METER_ANALYZER_ACTIVE_FILES:datasource,threadpool} # Which files could be meter analyzed, files split by ","
log-analyzer:
selector: ${SW_LOG_ANALYZER:default}
default:
lalFiles: ${SW_LOG_LAL_FILES:default}
malFiles: ${SW_LOG_MAL_FILES:""}
event-analyzer:
selector: ${SW_EVENT_ANALYZER:default}
default:
query:
selector: ${SW_QUERY:graphql}
graphql:
path: ${SW_QUERY_GRAPHQL_PATH:/graphql}
# Enable the log testing API to test the LAL.
# NOTE: This API evaluates untrusted code on the OAP server.
# A malicious script can do significant damage (steal keys and secrets, remove files and directories, install malware, etc).
# As such, please enable this API only when you completely trust your users.
enableLogTestTool: ${SW_QUERY_GRAPHQL_ENABLE_LOG_TEST_TOOL:false}
alarm:
selector: ${SW_ALARM:default}
default:
telemetry:
selector: ${SW_TELEMETRY:none}
none:
configuration:
selector: ${SW_CONFIGURATION:none}
none:
health-checker:
selector: ${SW_HEALTH_CHECKER:-}
default:
checkIntervalSeconds: ${SW_HEALTH_CHECKER_INTERVAL_SECONDS:5}
data-generator:
selector: ${SW_DATA_GENERATOR:default}
default:

View File

@ -0,0 +1,36 @@
/*
* 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.generator;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class IntGeneratorTest {
@Test
public void testFixedInt() {
final IntGenerator.Builder builder = new IntGenerator.Builder();
builder.setMin(1L);
builder.setMax(1L);
final IntGenerator generator = builder.build();
for (int i = 0; i < 100; i++) {
assertEquals(1, generator.next().intValue());
}
}
}

View File

@ -0,0 +1,55 @@
/*
* 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.generator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public final class SequenceGeneratorTest {
@Test
public void testSequence() {
SequenceGenerator generator =
new SequenceGenerator.Builder()
.setMin(1L)
.setMax(100L)
.build();
for (int i = 0; i < 10; i++) {
assertEquals(i + 1, generator.next().intValue());
}
}
@Test
public void testFluctuation() {
SequenceGenerator generator =
new SequenceGenerator.Builder()
.setMin(1L)
.setMax(100L)
.setFluctuation(1)
.build();
for (int i = 1; i < 10; i++) {
Long next = generator.next();
assertTrue(i <= next.intValue());
assertTrue(i * 2 >= next.intValue());
}
}
}

View File

@ -30,5 +30,6 @@
<modules>
<module>profile-exporter</module>
<module>data-generator</module>
</modules>
</project>