Add data-generator module to run OAP in testing mode, generating mock data for testing (#8725)
This commit is contained in:
parent
d2fcd83018
commit
3256b6c9d9
4
Makefile
4
Makefile
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
@ -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 "$@"
|
||||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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]`.
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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() {
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,5 +30,6 @@
|
|||
|
||||
<modules>
|
||||
<module>profile-exporter</module>
|
||||
<module>data-generator</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
|||
Loading…
Reference in New Issue