diff --git a/.gitmodules b/.gitmodules index 8011ff2bf149..5ecb21ea352d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "skywalking-ui"] path = skywalking-ui url = https://github.com/apache/skywalking-booster-ui.git +[submodule "oap-server/server-library/library-banyandb-client/src/main/proto"] + path = oap-server/server-library/library-banyandb-client/src/main/proto + url = https://github.com/apache/skywalking-banyandb-client-proto diff --git a/apm-dist/src/main/assembly/binary.xml b/apm-dist/src/main/assembly/binary.xml index 0f7a29454d7c..f6dbf452d329 100644 --- a/apm-dist/src/main/assembly/binary.xml +++ b/apm-dist/src/main/assembly/binary.xml @@ -60,7 +60,6 @@ metadata-service-mapping.yaml trace-sampling-policy-settings.yml hierarchy-definition.yml - bydb.dependencies.properties bydb.yml bydb-topn.yml oal/*.oal diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md index c40cf1b51381..9a496b0c61a9 100644 --- a/docs/en/changes/changes.md +++ b/docs/en/changes/changes.md @@ -16,6 +16,9 @@ * Bump up netty to 4.2.9.Final. * Add support for OpenSearch/ElasticSearch client certificate authentication. * Fix BanyanDB logs paging query. +* Replace BanyanDB Java client with native implementation. +* Remove `bydb.dependencies.properties` and set the compatible BanyanDB API version number in `${SW_STORAGE_BANYANDB_COMPATIBLE_SERVER_API_VERSIONS}` +* Fix trace profiling query time range condition. #### UI * Fix the missing icon in new native trace view. diff --git a/docs/en/setup/backend/backend-setup.md b/docs/en/setup/backend/backend-setup.md index 8d95dcd732fe..38198e03f5c1 100755 --- a/docs/en/setup/backend/backend-setup.md +++ b/docs/en/setup/backend/backend-setup.md @@ -20,8 +20,13 @@ You should set up the database ready before starting the backend. We recommend t If you want to use other databases, please read the [storage document](backend-storage.md). Use the docker mode to run BanyanDB containerized. +The compatible BanyanDB API version number could be found in `/config/bydb.yml` +``` +${SW_STORAGE_BANYANDB_COMPATIBLE_SERVER_API_VERSIONS} +``` +The compatible BanyanDB Server version number can get through the [API versions mapping](https://skywalking.apache.org/docs/skywalking-banyandb/latest/installation/versions/). + ```shell -# The compatible version number could be found in /config/bydb.dependencies.properties export BYDB_VERSION=xxx docker pull apache/skywalking-banyandb:${BYDB_VERSION} diff --git a/docs/en/setup/backend/configuration-vocabulary.md b/docs/en/setup/backend/configuration-vocabulary.md index 8e2e55911b8f..56ec52f16f39 100644 --- a/docs/en/setup/backend/configuration-vocabulary.md +++ b/docs/en/setup/backend/configuration-vocabulary.md @@ -352,23 +352,24 @@ The following table lists the configuration items: ### Global Configuration The global settings for the whole BanyanDB: -| Settings | Value(s) and Explanation | System Environment Variable¹ | Default | -|---------------------------------|-------------------------------------------------------------------------------------------------------|---------------------------------------------------------|-----------------| -| targets | Hosts with ports of the BanyanDB. | SW_STORAGE_BANYANDB_TARGETS | 127.0.0.1:17912 | -| maxBulkSize | The maximum size of write entities in a single batch write call. | SW_STORAGE_BANYANDB_MAX_BULK_SIZE | 10000 | -| flushInterval | Period of flush interval. In the timeunit of seconds. | SW_STORAGE_BANYANDB_FLUSH_INTERVAL | 15 | -| flushTimeout | The timeout seconds of a bulk flush. | SW_STORAGE_BANYANDB_FLUSH_TIMEOUT | 10 | -| concurrentWriteThreads | Concurrent consumer threads for batch writing. | SW_STORAGE_BANYANDB_CONCURRENT_WRITE_THREADS | 15 | -| profileTaskQueryMaxSize | Max size of ProfileTask to be fetched. | SW_STORAGE_BANYANDB_PROFILE_TASK_QUERY_MAX_SIZE | 200 | -| resultWindowMaxSize | The maximum size of dataset when the OAP loads cache, such as network aliases. | SW_STORAGE_BANYAND_QUERY_MAX_WINDOW_SIZE | 10000 | -| metadataQueryMaxSize | The maximum size of metadata per query. | SW_STORAGE_BANYAND_QUERY_MAX_SIZE | 10000 | -| segmentQueryMaxSize | The maximum size of trace segments per query. | SW_STORAGE_BANYAND_QUERY_SEGMENT_SIZE | 200 | -| asyncProfilerTaskQueryMaxSize | Max size of AsyncProfilerTask to be fetched. | SW_STORAGE_BANYANDB_ASYNC_PROFILER_TASK_QUERY_MAX_SIZE | 200 | -| profileDataQueryScrollBatchSize | The batch size of query profiling data. | SW_STORAGE_BANYAND_QUERY_PROFILE_DATA_BATCH_SIZE | 100 | -| user | The username for BanyanDB authentication. | SW_STORAGE_BANYANDB_USER | - | -| password | The password for BanyanDB authentication. | SW_STORAGE_BANYANDB_PASSWORD | - | -| sslTrustCAPath | If the BanyanDB server is configured with TLS, config the TLS cert file path and open tls connection. | SW_STORAGE_BANYANDB_SSL_TRUST_CA_PATH | - | -| cleanupUnusedTopNRules | Cleanup TopN rules in BanyanDB server that are not configured in the bydb-topn.yml config. | SW_STORAGE_BANYANDB_CLEANUP_UNUSED_TOPN_RULES | true | +| Settings | Value(s) and Explanation | System Environment Variable¹ | Default | +|---------------------------------|-------------------------------------------------------------------------------------------------------|--------------------------------------------------------|-------------------| +| targets | Hosts with ports of the BanyanDB. | SW_STORAGE_BANYANDB_TARGETS | 127.0.0.1:17912 | +| maxBulkSize | The maximum size of write entities in a single batch write call. | SW_STORAGE_BANYANDB_MAX_BULK_SIZE | 10000 | +| flushInterval | Period of flush interval. In the timeunit of seconds. | SW_STORAGE_BANYANDB_FLUSH_INTERVAL | 15 | +| flushTimeout | The timeout seconds of a bulk flush. | SW_STORAGE_BANYANDB_FLUSH_TIMEOUT | 10 | +| concurrentWriteThreads | Concurrent consumer threads for batch writing. | SW_STORAGE_BANYANDB_CONCURRENT_WRITE_THREADS | 15 | +| profileTaskQueryMaxSize | Max size of ProfileTask to be fetched. | SW_STORAGE_BANYANDB_PROFILE_TASK_QUERY_MAX_SIZE | 200 | +| resultWindowMaxSize | The maximum size of dataset when the OAP loads cache, such as network aliases. | SW_STORAGE_BANYAND_QUERY_MAX_WINDOW_SIZE | 10000 | +| metadataQueryMaxSize | The maximum size of metadata per query. | SW_STORAGE_BANYAND_QUERY_MAX_SIZE | 10000 | +| segmentQueryMaxSize | The maximum size of trace segments per query. | SW_STORAGE_BANYAND_QUERY_SEGMENT_SIZE | 200 | +| asyncProfilerTaskQueryMaxSize | Max size of AsyncProfilerTask to be fetched. | SW_STORAGE_BANYANDB_ASYNC_PROFILER_TASK_QUERY_MAX_SIZE | 200 | +| profileDataQueryScrollBatchSize | The batch size of query profiling data. | SW_STORAGE_BANYAND_QUERY_PROFILE_DATA_BATCH_SIZE | 100 | +| user | The username for BanyanDB authentication. | SW_STORAGE_BANYANDB_USER | - | +| password | The password for BanyanDB authentication. | SW_STORAGE_BANYANDB_PASSWORD | - | +| sslTrustCAPath | If the BanyanDB server is configured with TLS, config the TLS cert file path and open tls connection. | SW_STORAGE_BANYANDB_SSL_TRUST_CA_PATH | - | +| cleanupUnusedTopNRules | Cleanup TopN rules in BanyanDB server that are not configured in the bydb-topn.yml config. | SW_STORAGE_BANYANDB_CLEANUP_UNUSED_TOPN_RULES | true | +| namespace | The namespace in BanyanDB to store the data of OAP. | SW_NAMESPACE | default | ### Group Configuration The settings for each group: diff --git a/docs/en/setup/backend/storages/banyandb.md b/docs/en/setup/backend/storages/banyandb.md index a4611b57d763..03eef785e647 100644 --- a/docs/en/setup/backend/storages/banyandb.md +++ b/docs/en/setup/backend/storages/banyandb.md @@ -2,18 +2,12 @@ [BanyanDB](https://github.com/apache/skywalking-banyandb) is a dedicated storage implementation developed by the SkyWalking Team and the community. Activate BanyanDB as the storage by setting the storage provider to **banyandb**. -The BanyanDB server compatibility relies on API and release versions, which are defined in `bydb.dependencies.properties` -```shell -# BanyanDB version is the version number of BanyanDB Server release. -# This is the bundled and tested BanyanDB release version -bydb.version=x.y -# BanyanDB API version is the version number of the BanyanDB query APIs -# OAP server has bundled implementation of BanyanDB Java client. -# Please check BanyanDB documentation for the API version compatibility. -# https://skywalking.apache.org/docs/skywalking-banyandb/next/installation/versions -# Each `bydb.api.version` could have multiple compatible release version(`bydb.version`). -bydb.api.version=x.y +The BanyanDB server compatibility relies on API and release versions, +The compatible BanyanDB API version number could be found in `/config/bydb.yml` +``` +${SW_STORAGE_BANYANDB_COMPATIBLE_SERVER_API_VERSIONS} ``` +The compatible BanyanDB Server version number can get through the [API versions mapping](https://skywalking.apache.org/docs/skywalking-banyandb/latest/installation/versions/). If the BanyanDB server API version is not compatible with the OAP server, the OAP server will not start, and the following error message will be displayed: ```shell @@ -68,6 +62,11 @@ global: sslTrustCAPath: ${SW_STORAGE_BANYANDB_SSL_TRUST_CA_PATH:""} # Cleanup TopN rules in BanyanDB server that are not configured in the bydb-topn.yml config. cleanupUnusedTopNRules: ${SW_STORAGE_BANYANDB_CLEANUP_UNUSED_TOPN_RULES:true} + # The namespace in BanyanDB to store the data of OAP, if not set, the default is "sw". + # OAP will create BanyanDB Groups using the format of "{namespace}_{group name}", such as "sw_records". + namespace: ${SW_NAMESPACE:"sw"} + # The compatible server API versions of BanyanDB. + compatibleServerApiVersions: ${SW_STORAGE_BANYANDB_COMPATIBLE_SERVER_API_VERSIONS:"0.9"} groups: # The group settings of record. @@ -365,7 +364,6 @@ BanyanDB Server supports two installation modes: Use the docker mode to run BanyanDB containerized. ```shell -# The compatible version number could be found in /config/bydb.dependencies.properties export BYDB_VERSION=xxx docker pull apache/skywalking-banyandb:${BYDB_VERSION} @@ -393,4 +391,4 @@ docker run -d \ - **Cluster Mode**: Suitable for large-scale deployments. - **Configuration**: `targets` is the IP address/hostname and port of the `liaison` nodes, separated by commas. `Liaison` nodes are the entry points of the BanyanDB cluster. -For more details, refer to the documentation of [BanyanDB](https://skywalking.apache.org/docs/skywalking-banyandb/latest/readme/) and the [BanyanDB Java Client](https://github.com/apache/skywalking-banyandb-java-client) subprojects. +For more details, refer to the documentation of [BanyanDB](https://skywalking.apache.org/docs/skywalking-banyandb/latest/readme/). diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/trace/ProfileTaskQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/trace/ProfileTaskQueryService.java index a3db0ebc4849..f62b55ea695b 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/trace/ProfileTaskQueryService.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/trace/ProfileTaskQueryService.java @@ -191,17 +191,12 @@ public ProfileAnalyzation getProfileAnalyze(final List getTaskSegments(String taskId) throws IOException { List records = getProfileThreadSnapshotQueryDAO().queryRecords(taskId); List profiledSegmentIdList = records.stream().map(ProfileThreadSnapshotRecord::getSegmentId).collect(Collectors.toList()); - long endTimestamp = 0; - for (ProfileThreadSnapshotRecord record : records) { - if (record.getDumpTime() > endTimestamp) { - endTimestamp = record.getDumpTime(); - } - } - long startTimestamp = endTimestamp - 5 * 60 * 1000; // 5 minutes + ProfileTask profileTask = getProfileTaskDAO().getById(taskId); + long endTimestamp = profileTask.getStartTime() + (long) profileTask.getDuration() * 60 * 1000; // duration minute to ms Duration duration = new Duration(); duration.setStep(Step.SECOND); - DateTime endTime = new DateTime(endTimestamp); - DateTime startTime = new DateTime(startTimestamp); + DateTime endTime = new DateTime(endTimestamp + 15 * 60 * 1000); // 15 minutes later to cover delay + DateTime startTime = new DateTime(endTimestamp - 10 * 60 * 1000); // 10 minutes before end time duration.setStart(startTime.toString("yyyy-MM-dd HHmmss")); duration.setEnd(endTime.toString("yyyy-MM-dd HHmmss")); return getTraceQueryDAO().queryBySegmentIdList(profiledSegmentIdList, duration); diff --git a/oap-server/server-library/library-banyandb-client/pom.xml b/oap-server/server-library/library-banyandb-client/pom.xml new file mode 100644 index 000000000000..933e9ee4e775 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/pom.xml @@ -0,0 +1,143 @@ + + + + + + server-library + org.apache.skywalking + ${revision} + + 4.0.0 + library-banyandb-client + + + io.grpc + grpc-netty + + + io.netty + netty-handler + + + io.netty + netty-codec-http2 + + + com.google.protobuf + protobuf-java + + + io.grpc + grpc-stub + + + io.grpc + grpc-protobuf + + + build.buf.protoc-gen-validate + protoc-gen-validate + ${bufbuild.protoc-gen-validate.version} + pom + + + build.buf.protoc-gen-validate + pgv-java-stub + ${bufbuild.protoc-gen-validate.version} + + + io.grpc + grpc-testing + test + + + org.apache.skywalking + server-testing + ${project.version} + + + org.apache.skywalking + library-integration-test + ${project.version} + + + + + + kr.motd.maven + os-maven-plugin + ${os-maven-plugin.version} + + + initialize + + detect + + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + ${protobuf-maven-plugin.version} + + + + com.google.protobuf:protoc:${com.google.protobuf.protoc.version}:exe:${os.detected.classifier} + + grpc-java + + io.grpc:protoc-gen-grpc-java:${protoc-gen-grpc-java.plugin.version}:exe:${os.detected.classifier} + + ${project.basedir}/src/main/proto/proto + + **/*.proto + + + + + grpc-build + + compile + compile-custom + + + + protoc-java-pgv + + compile-custom + + + lang=java + java-pgv + + build.buf.protoc-gen-validate:protoc-gen-validate:${bufbuild.protoc-gen-validate.version}:exe:${os.detected.classifier} + + + + + + + + diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractCriteria.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractCriteria.java new file mode 100644 index 000000000000..ad044c20f444 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractCriteria.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client; + +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +public abstract class AbstractCriteria { + public abstract BanyandbModel.Criteria build(); +} + +abstract class LogicalExpression extends AbstractCriteria { + abstract AbstractCriteria left(); + + abstract AbstractCriteria right(); +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractQuery.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractQuery.java new file mode 100644 index 000000000000..601388d01b14 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractQuery.java @@ -0,0 +1,239 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.base.Strings; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.InvalidReferenceException; + +public abstract class AbstractQuery { + /** + * Group of the current entity + */ + protected final List groups; + /** + * Owner name of the current entity + */ + protected final String name; + /** + * The time range for query. + */ + protected final TimestampRange timestampRange; + /** + * Query conditions. + */ + protected final List conditions; + + /** + * The projections of query result. + * These should have defined in the schema. + */ + protected final Map tagProjections; + + /** + * Query criteria. + */ + protected AbstractCriteria criteria; + + /** + * Enable or disable trace. + */ + protected boolean trace; + + public AbstractQuery(List groups, + String name, + TimestampRange timestampRange, + Map tagProjections) { + this.groups = groups; + this.name = name; + this.timestampRange = timestampRange; + this.conditions = new ArrayList<>(10); + this.tagProjections = tagProjections; + } + + /** + * Constructor with tag projections as a set of tag names which have no specified tag family. + * Such as Property/Trace query + */ + public AbstractQuery(List groups, + String name, + TimestampRange timestampRange, + Set tagProjections) { + this.groups = groups; + this.name = name; + this.timestampRange = timestampRange; + this.conditions = new ArrayList<>(10); + this.tagProjections = new HashMap<>(); + tagProjections.forEach(tagName -> this.tagProjections.put(tagName, null)); + } + + /** + * Fluent API for appending a and + * + * @param condition the query condition to be appended + */ + public AbstractQuery and(PairQueryCondition condition) { + this.conditions.add(new LogicalExpression(BanyandbModel.LogicalExpression.LogicalOp.LOGICAL_OP_AND, condition)); + return this; + } + + /** + * Fluent API for appending or + * + * @param condition the query condition to be appended + */ + public AbstractQuery or(PairQueryCondition condition) { + this.conditions.add(new LogicalExpression(BanyandbModel.LogicalExpression.LogicalOp.LOGICAL_OP_OR, condition)); + return this; + } + + /** + * Fluent API for appending query criteria + * + * @param criteria the query criteria to be appended + */ + public AbstractQuery criteria(AbstractCriteria criteria) { + this.criteria = criteria; + return this; + } + + /** + * Enable trace for the query. + */ + public AbstractQuery enableTrace() { + this.trace = true; + return this; + } + + /** + * @return QueryRequest for gRPC level query. + * @throws BanyanDBException thrown from entity build, e.g. invalid reference to non-exist fields or tags. + */ + abstract T build() throws BanyanDBException; + + protected Optional buildCriteria() { + if (criteria != null) { + return Optional.of(criteria.build()); + } + if (conditions.isEmpty()) { + return Optional.empty(); + } + if (conditions.size() == 1) { + return Optional.of(conditions.get(0).getCond().build()); + } + return Optional.of(conditions.stream() + .reduce(null, (criteria, logicalExpression) -> { + BanyandbModel.LogicalExpression.Builder b = BanyandbModel.LogicalExpression.newBuilder(); + if (criteria != null) { + b.setRight(criteria); + } + return BanyandbModel.Criteria.newBuilder() + .setLe(b.setOp(logicalExpression.getOp()) + .setLeft(logicalExpression.getCond().build())).build(); + }, (first, second) -> second)); + } + + protected BanyandbModel.TagProjection buildTagProjections() throws BanyanDBException { + return this.buildTagProjections(this.tagProjections.keySet()); + } + + protected BanyandbModel.TagProjection buildTagProjections(Iterable tagProjections) throws BanyanDBException { + final ListMultimap projectionMap = ArrayListMultimap.create(); + for (final String tagName : tagProjections) { + final String tagFamily = this.tagProjections.get(tagName); + if (Strings.isNullOrEmpty(tagFamily)) { + throw InvalidReferenceException.fromInvalidTag(tagName); + } + projectionMap.put(tagFamily, tagName); + } + + final BanyandbModel.TagProjection.Builder b = BanyandbModel.TagProjection.newBuilder(); + for (final String tagFamilyName : projectionMap.keySet()) { + b.addTagFamilies(BanyandbModel.TagProjection.TagFamily.newBuilder() + .setName(tagFamilyName) + .addAllTags(projectionMap.get(tagFamilyName)) + .build()); + } + return b.build(); + } + + public static class OrderBy { + /** + * The field name for ordering. + */ + private final String indexRuleName; + /** + * The type of ordering. + */ + private final Sort type; + + /** + * Create an orderBy condition with given rule name and sort type + */ + public OrderBy(final String indexRuleName, final Sort type) { + this.indexRuleName = indexRuleName; + this.type = type; + } + + /** + * Create an orderBy condition with timestamp and sort type + */ + public OrderBy(final Sort type) { + this.indexRuleName = null; + this.type = type; + } + + BanyandbModel.QueryOrder build() { + final BanyandbModel.QueryOrder.Builder builder = BanyandbModel.QueryOrder.newBuilder(); + if (indexRuleName != null) { + builder.setIndexRuleName(indexRuleName); + } + builder.setSort( + Sort.DESC.equals(type) ? BanyandbModel.Sort.SORT_DESC : BanyandbModel.Sort.SORT_ASC); + return builder.build(); + } + } + + @RequiredArgsConstructor + @Getter(AccessLevel.PROTECTED) + public enum Sort { + UNSPECIFIED, ASC, DESC; + } + + @AllArgsConstructor + @Getter + static class LogicalExpression { + private final BanyandbModel.LogicalExpression.LogicalOp op; + + private final PairQueryCondition cond; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractWrite.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractWrite.java new file mode 100644 index 000000000000..413545d9b598 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/AbstractWrite.java @@ -0,0 +1,67 @@ +/* + * 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.library.banyandb.v1.client; + +import java.util.Optional; +import lombok.Getter; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; + +public abstract class AbstractWrite

{ + /** + * Timestamp represents the time of the current data point, in milliseconds. + *

+ * When to set: + *

    + *
  • Stream and Measure writes: This field must be set to indicate the event time.
  • + *
  • Trace writes: This field is not needed and should be left unset; trace data does not require an explicit timestamp here.
  • + *
+ */ + @Getter + protected Optional timestamp; + + @Getter + protected final BanyandbCommon.Metadata entityMetadata; + + public AbstractWrite(BanyandbCommon.Metadata entityMetadata, long timestamp) { + this(entityMetadata); + this.timestamp = Optional.of(timestamp); + } + + /** + * Build a write request without initial timestamp. + */ + AbstractWrite(BanyandbCommon.Metadata entityMetadata) { + if (entityMetadata == null) { + throw new IllegalArgumentException("metadata not found"); + } + this.entityMetadata = entityMetadata; + } + + public P build() { + return build(entityMetadata); + } + + public P buildOnlyValues() { + return buildValues(); + } + + protected abstract P build(BanyandbCommon.Metadata metadata); + + protected abstract P buildValues(); +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/And.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/And.java new file mode 100644 index 000000000000..fba9ac837cc3 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/And.java @@ -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.library.banyandb.v1.client; + +import lombok.Builder; +import lombok.Getter; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +@Builder +@Getter +public class And extends LogicalExpression { + private final AbstractCriteria left; + private final AbstractCriteria right; + + @Override + public BanyandbModel.Criteria build() { + return BanyandbModel.Criteria.newBuilder() + .setLe(BanyandbModel.LogicalExpression.newBuilder() + .setLeft(left.build()) + .setRight(right.build()) + .setOp(BanyandbModel.LogicalExpression.LogicalOp.LOGICAL_OP_AND) + .build()) + .build(); + } + + public static And create(AbstractCriteria left, AbstractCriteria right) { + return And.builder().left(left).right(right).build(); + } + + @Override + AbstractCriteria left() { + return left; + } + + @Override + AbstractCriteria right() { + return right; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClient.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClient.java new file mode 100644 index 000000000000..0d0f82e77fba --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClient.java @@ -0,0 +1,1114 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import com.google.protobuf.Timestamp; +import io.grpc.Channel; +import io.grpc.ClientInterceptors; +import io.grpc.ManagedChannel; +import io.grpc.Status; +import java.io.Closeable; +import java.io.IOException; +import java.net.URI; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.Collectors; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Group; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.common.v1.ServiceGrpc; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRule; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRuleBinding; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Measure; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Stream; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Subject; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TopNAggregation; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Trace; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; +import org.apache.skywalking.banyandb.measure.v1.MeasureServiceGrpc; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty; +import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; +import org.apache.skywalking.banyandb.stream.v1.StreamServiceGrpc; +import org.apache.skywalking.banyandb.trace.v1.BanyandbTrace; +import org.apache.skywalking.banyandb.trace.v1.TraceServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.auth.AuthInterceptor; +import org.apache.skywalking.library.banyandb.v1.client.grpc.HandleExceptionsWith; +import org.apache.skywalking.library.banyandb.v1.client.grpc.channel.ChannelManager; +import org.apache.skywalking.library.banyandb.v1.client.grpc.channel.DefaultChannelFactory; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.GroupMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.metadata.IndexRuleBindingMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.metadata.IndexRuleMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.metadata.MeasureMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.metadata.PropertyMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.metadata.ResourceExist; +import org.apache.skywalking.library.banyandb.v1.client.metadata.StreamMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.metadata.TopNAggregationMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.metadata.TraceMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.util.TimeUtils; +import org.apache.skywalking.oap.server.library.util.StringUtil; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +/** + * BanyanDBClient represents a client instance interacting with BanyanDB server. + * This is built on the top of BanyanDB v1 gRPC APIs. + * + *
{@code
+ * // use `default` group
+ * client = new BanyanDBClient("127.0.0.1", 17912);
+ * // to send any request, a connection to the server must be estabilished
+ * client.connect();
+ * }
+ */ +@Slf4j +public class BanyanDBClient implements Closeable { + public static final ZonedDateTime DEFAULT_EXPIRE_AT = ZonedDateTime.of(2099, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); + private final String[] targets; + /** + * Options for server connection. + */ + @Getter + private final Options options; + /** + * gRPC connection. + */ + @Getter + private volatile Channel channel; + /** + * gRPC client stub + */ + @Getter + private StreamServiceGrpc.StreamServiceStub streamServiceStub; + /** + * gRPC client stub + */ + @Getter + private MeasureServiceGrpc.MeasureServiceStub measureServiceStub; + /** + * gRPC client stub + */ + @Getter + private TraceServiceGrpc.TraceServiceStub traceServiceStub; + /** + * gRPC future stub. + */ + @Getter + private StreamServiceGrpc.StreamServiceBlockingStub streamServiceBlockingStub; + /** + * gRPC future stub. + */ + @Getter + private MeasureServiceGrpc.MeasureServiceBlockingStub measureServiceBlockingStub; + /** + * gRPC future stub. + */ + @Getter + private TraceServiceGrpc.TraceServiceBlockingStub traceServiceBlockingStub; + /** + * The connection status. + */ + private volatile boolean isConnected = false; + /** + * A lock to control the race condition in establishing and disconnecting network connection. + */ + private final ReentrantLock connectionEstablishLock; + + /** + * Create a BanyanDB client instance with a default options. + * + * @param targets server targets + */ + public BanyanDBClient(String... targets) { + this(targets, new Options()); + } + + /** + * Create a BanyanDB client instance with a customized options. + * + * @param targets server targets + * @param options customized options + */ + public BanyanDBClient(String[] targets, Options options) { + String[] tt = Preconditions.checkNotNull(targets, "targets"); + checkState(tt.length > 0, "targets' size must be more than 1"); + tt = Arrays.stream(tt).filter(t -> !Strings.isNullOrEmpty(t)).toArray(size -> new String[size]); + checkState(tt.length > 0, "valid targets' size must be more than 1"); + this.targets = tt; + this.options = options; + this.connectionEstablishLock = new ReentrantLock(); + } + + /** + * Construct a connection to the server. + * + * @throws IOException thrown if fail to create a connection + */ + public void connect() throws IOException { + connectionEstablishLock.lock(); + try { + if (!isConnected) { + URI[] addresses = new URI[this.targets.length]; + for (int i = 0; i < this.targets.length; i++) { + addresses[i] = URI.create("//" + this.targets[i]); + } + Channel rawChannel = ChannelManager.create(this.options.buildChannelManagerSettings(), + new DefaultChannelFactory(addresses, this.options)); + Channel interceptedChannel = rawChannel; + // register auth interceptor + String username = options.getUsername(); + String password = options.getPassword(); + if (StringUtil.isNotBlank(username) && StringUtil.isNotBlank(password)) { + interceptedChannel = ClientInterceptors.intercept(rawChannel, + new AuthInterceptor(username, password)); + } + // Ensure this.channel is assigned only once. + this.channel = interceptedChannel; + streamServiceBlockingStub = StreamServiceGrpc.newBlockingStub(this.channel); + measureServiceBlockingStub = MeasureServiceGrpc.newBlockingStub(this.channel); + traceServiceBlockingStub = TraceServiceGrpc.newBlockingStub(this.channel); + streamServiceStub = StreamServiceGrpc.newStub(this.channel); + measureServiceStub = MeasureServiceGrpc.newStub(this.channel); + traceServiceStub = TraceServiceGrpc.newStub(this.channel); + isConnected = true; + } + } finally { + connectionEstablishLock.unlock(); + } + } + + @VisibleForTesting + void connect(Channel channel) { + connectionEstablishLock.lock(); + try { + if (!isConnected) { + this.channel = channel; + streamServiceBlockingStub = StreamServiceGrpc.newBlockingStub(this.channel); + measureServiceBlockingStub = MeasureServiceGrpc.newBlockingStub(this.channel); + traceServiceBlockingStub = TraceServiceGrpc.newBlockingStub(this.channel); + streamServiceStub = StreamServiceGrpc.newStub(this.channel); + measureServiceStub = MeasureServiceGrpc.newStub(this.channel); + traceServiceStub = TraceServiceGrpc.newStub(this.channel); + isConnected = true; + } + } finally { + connectionEstablishLock.unlock(); + } + } + + /** + * Build a MeasureWrite request. + * + * @param group the group of the measure + * @param name the name of the measure + * @param timestamp the timestamp of the measure + * @return the request to be built + */ + public MeasureWrite createMeasureWrite(String group, String name, long timestamp) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + return new MeasureWrite(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build(), timestamp); + } + + /** + * Build a StreamWrite request. + * + * @param group the group of the stream + * @param name the name of the stream + * @param elementId the primary key of the stream + * @return the request to be built + */ + public StreamWrite createStreamWrite(String group, String name, final String elementId) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + return new StreamWrite(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build(), elementId); + } + + /** + * Build a TraceWrite request without initial timestamp. + * + * @param group the group of the trace + * @param name the name of the trace + * @return the request to be built + */ + public TraceWrite createTraceWrite(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + return new TraceWrite(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()); + } + + /** + * Query streams according to given conditions + * + * @param streamQuery condition for query + * @return hint streams. + */ + public StreamQueryResponse query(StreamQuery streamQuery) throws BanyanDBException { + checkState(this.streamServiceStub != null, "stream service is null"); + + for (String group : streamQuery.groups) { + final BanyandbStream.QueryResponse response = + HandleExceptionsWith.callAndTranslateApiException(() -> + this.streamServiceBlockingStub + .withDeadlineAfter( + this.getOptions().getDeadline(), + TimeUnit.SECONDS + ) + .query(streamQuery.build())); + return new StreamQueryResponse(response); + } + throw new RuntimeException("No metadata found for the query"); + } + + /** + * Query TopN according to given conditions + * + * @param topNQuery condition for query + * @return hint topN. + */ + public TopNQueryResponse query(TopNQuery topNQuery) throws BanyanDBException { + checkState(this.measureServiceStub != null, "measure service is null"); + + final BanyandbMeasure.TopNResponse response = HandleExceptionsWith.callAndTranslateApiException(() -> + this.measureServiceBlockingStub + .withDeadlineAfter(this.getOptions().getDeadline(), TimeUnit.SECONDS) + .topN(topNQuery.build())); + return new TopNQueryResponse(response); + } + + /** + * Query measures according to given conditions + * + * @param measureQuery condition for query + * @return hint measures. + */ + public MeasureQueryResponse query(MeasureQuery measureQuery) throws BanyanDBException { + checkState(this.streamServiceStub != null, "measure service is null"); + for (String group : measureQuery.groups) { + final BanyandbMeasure.QueryResponse response = + HandleExceptionsWith.callAndTranslateApiException(() -> + this.measureServiceBlockingStub + .withDeadlineAfter( + this.getOptions() + .getDeadline(), + TimeUnit.SECONDS + ) + .query( + measureQuery.build())); + return new MeasureQueryResponse(response); + } + throw new RuntimeException("No metadata found for the query"); + } + + /** + * Query traces according to given conditions + * + * @param traceQuery condition for query + * @return trace query response. + */ + public TraceQueryResponse query(TraceQuery traceQuery) throws BanyanDBException { + checkState(this.traceServiceStub != null, "trace service is null"); + + for (String group : traceQuery.groups) { + final BanyandbTrace.QueryResponse response = + HandleExceptionsWith.callAndTranslateApiException(() -> + this.traceServiceBlockingStub + .withDeadlineAfter( + this.getOptions().getDeadline(), + TimeUnit.SECONDS + ) + .query(traceQuery.build())); + return new TraceQueryResponse(response); + + } + throw new RuntimeException("No metadata found for the query"); + } + + /** + * Define a new group and attach to the current client. + * + * @param group the group to be created + * @return a grouped client + */ + public Group define(Group group) throws BanyanDBException { + GroupMetadataRegistry registry = new GroupMetadataRegistry(checkNotNull(this.channel)); + registry.create(group); + return registry.get(null, group.getMetadata().getName()); + } + + /** + * Define a new stream + * + * @param stream the stream to be created + */ + public void define(Stream stream) throws BanyanDBException { + StreamMetadataRegistry streamRegistry = new StreamMetadataRegistry(checkNotNull(this.channel)); + long modRevision = streamRegistry.create(stream); + stream = stream.toBuilder().setMetadata(stream.getMetadata().toBuilder().setModRevision(modRevision)).build(); + } + + /** + * Define a new stream with index rules, + * @param stream the stream to be created + * @param indexRules the index rules to be created + */ + public void define(Stream stream, List indexRules) throws BanyanDBException { + define(stream); + defineIndexRules(stream, indexRules); + } + + /** + * Define a new measure + * + * @param measure the measure to be created + */ + public void define(Measure measure) throws BanyanDBException { + MeasureMetadataRegistry measureRegistry = new MeasureMetadataRegistry(checkNotNull(this.channel)); + long modRevision = measureRegistry.create(measure); + measure = measure.toBuilder().setMetadata(measure.getMetadata().toBuilder().setModRevision(modRevision)).build(); + } + + /** + * Define a new measure with index rules + * @param measure the measure to be created + * @param indexRules the index rules to be created + */ + public void define(Measure measure, List indexRules) throws BanyanDBException { + define(measure); + defineIndexRules(measure, indexRules); + } + + /** + * Define a new TopNAggregation + * + * @param topNAggregation the topN rule to be created + */ + public void define(TopNAggregation topNAggregation) throws BanyanDBException { + TopNAggregationMetadataRegistry registry = new TopNAggregationMetadataRegistry(checkNotNull(this.channel)); + registry.create(topNAggregation); + } + + /** + * Define a new IndexRule + * @param indexRule the index rule to be created + */ + public void define(IndexRule indexRule) throws BanyanDBException { + IndexRuleMetadataRegistry registry = new IndexRuleMetadataRegistry(checkNotNull(this.channel)); + registry.create(indexRule); + } + + /** + * Define a new IndexRuleBinding, if the beginAt and expireAt are not set, the default value will be used. + * The default value of beginAt is the current time, and the default value of expireAt is 2099-01-01 00:00:00 UTC. + * @param indexRuleBinding the index rule binding to be created + */ + public void define(IndexRuleBinding indexRuleBinding) throws BanyanDBException { + ZonedDateTime beginAt = indexRuleBinding.getBeginAt() == Timestamp.getDefaultInstance() ? ZonedDateTime.now() : TimeUtils.parseTimestamp(indexRuleBinding.getBeginAt()); + ZonedDateTime expireAt = indexRuleBinding.getExpireAt() == Timestamp.getDefaultInstance() ? DEFAULT_EXPIRE_AT : TimeUtils.parseTimestamp(indexRuleBinding.getExpireAt()); + this.define(indexRuleBinding, beginAt, expireAt); + } + + /** + * Define a new IndexRuleBinding + * @param indexRuleBinding the index rule binding to be created + * @param beginAt the beginning time of the index rule binding + * @param expireAt the expiry time of the index rule binding + */ + public void define(IndexRuleBinding indexRuleBinding, ZonedDateTime beginAt, ZonedDateTime expireAt) throws BanyanDBException { + IndexRuleBindingMetadataRegistry registry = new IndexRuleBindingMetadataRegistry(checkNotNull(this.channel)); + indexRuleBinding = indexRuleBinding.toBuilder() + .setBeginAt(TimeUtils.buildTimestamp(beginAt)) + .setExpireAt(TimeUtils.buildTimestamp(expireAt)) + .build(); + registry.create(indexRuleBinding); + } + + /** + * Bind index rule to the stream + * By default, the index rule binding will be active from now, and it will never be expired. + * @param stream the subject of index rule binding + * @param indexRules rules to be bounded + */ + public void defineIndexRules(Stream stream, List indexRules) throws BanyanDBException { + Preconditions.checkArgument(stream != null, "stream cannot be null"); + + IndexRuleMetadataRegistry irRegistry = new IndexRuleMetadataRegistry(checkNotNull(this.channel)); + for (final IndexRule ir : indexRules) { + try { + irRegistry.create(ir); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.ALREADY_EXISTS)) { + continue; + } + throw ex; + } + } + if (indexRules.isEmpty()) { + return; + } + + List indexRuleNames = indexRules.stream() + .map(indexRule -> indexRule.getMetadata().getName()) + .collect(Collectors.toList()); + + IndexRuleBinding binding = IndexRuleBinding.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup( + stream.getMetadata().getGroup()) + .setName( + stream.getMetadata().getName())) + .setSubject(Subject.newBuilder() + .setName(stream.getMetadata() + .getName()) + .setCatalog( + BanyandbCommon.Catalog.CATALOG_STREAM)) + .addAllRules(indexRuleNames).build(); + this.define(binding); + } + + /** + * Bind index rule to the measure. + * By default, the index rule binding will be active from now, and it will never be expired. + * + * @param measure the subject of index rule binding + * @param indexRules rules to be bounded + */ + public void defineIndexRules(Measure measure, List indexRules) throws BanyanDBException { + Preconditions.checkArgument(measure != null, "measure cannot be null"); + + IndexRuleMetadataRegistry irRegistry = new IndexRuleMetadataRegistry(checkNotNull(this.channel)); + for (final IndexRule ir : indexRules) { + try { + irRegistry.create(ir); + } catch (BanyanDBException ex) { + // multiple entity can share a single index rule + if (ex.getStatus().equals(Status.Code.ALREADY_EXISTS)) { + continue; + } + throw ex; + } + } + if (indexRules.isEmpty()) { + return; + } + + List indexRuleNames = indexRules.stream().map(indexRule -> indexRule.getMetadata().getName()).collect(Collectors.toList()); + + IndexRuleBinding binding = IndexRuleBinding.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup( + measure.getMetadata().getGroup()) + .setName( + measure.getMetadata().getName())) + .setSubject(Subject.newBuilder() + .setName(measure.getMetadata() + .getName()) + .setCatalog( + BanyandbCommon.Catalog.CATALOG_MEASURE)) + .addAllRules(indexRuleNames).build(); + this.define(binding); + } + + /** + * Update the group + * + * @param group the group to be updated + */ + public void update(Group group) throws BanyanDBException { + GroupMetadataRegistry registry = new GroupMetadataRegistry(checkNotNull(this.channel)); + registry.update(group); + } + + /** + * Update the stream + * @param stream the stream to be updated + */ + public void update(Stream stream) throws BanyanDBException { + StreamMetadataRegistry streamRegistry = new StreamMetadataRegistry(checkNotNull(this.channel)); + streamRegistry.update(stream); + } + + /** + * Update the measure + * + * @param measure the measure to be updated + */ + public void update(Measure measure) throws BanyanDBException { + MeasureMetadataRegistry measureRegistry = new MeasureMetadataRegistry(checkNotNull(this.channel)); + measureRegistry.update(measure); + } + + /** + * Update the TopNAggregation + * @param topNAggregation the topN rule to be updated + */ + public void update(TopNAggregation topNAggregation) throws BanyanDBException { + TopNAggregationMetadataRegistry registry = new TopNAggregationMetadataRegistry(checkNotNull(this.channel)); + registry.update(topNAggregation); + } + + /** + * Update the IndexRule + * @param indexRule the index rule to be updated + */ + public void update(IndexRule indexRule) throws BanyanDBException { + IndexRuleMetadataRegistry registry = new IndexRuleMetadataRegistry(checkNotNull(this.channel)); + registry.update(indexRule); + } + + /** + * Update the IndexRuleBinding + * @param indexRuleBinding the index rule binding to be updated + */ + public void update(IndexRuleBinding indexRuleBinding) throws BanyanDBException { + IndexRuleBindingMetadataRegistry registry = new IndexRuleBindingMetadataRegistry(checkNotNull(this.channel)); + registry.update(indexRuleBinding); + } + + /** + * Delete the group + * @param name name of the group + * @return true if the group is deleted successfully + */ + public boolean deleteGroup(String name) throws BanyanDBException { + GroupMetadataRegistry registry = new GroupMetadataRegistry(checkNotNull(this.channel)); + return registry.delete(name, name); + } + + /** + * Delete a stream + * @param group the group name of the stream + * @param name the name of the stream + * @return true if the stream is deleted successfully + */ + public boolean deleteStream(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + StreamMetadataRegistry streamRegistry = new StreamMetadataRegistry(checkNotNull(this.channel)); + return streamRegistry.delete(group, name); + } + + /** + * Delete a measure + * @param group the group name of the measure + * @param name the name of the measure + * @return true if the measure is deleted successfully + */ + public boolean deleteMeasure(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + MeasureMetadataRegistry measureRegistry = new MeasureMetadataRegistry(checkNotNull(this.channel)); + return measureRegistry.delete(group, name); + } + + /** + * Delete the TopNAggregation + * @param group the group name of the topN rule + * @param name the name of the topN rule + * @return true if the topN rule is deleted successfully + */ + public boolean deleteTopNAggregation(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + TopNAggregationMetadataRegistry registry = new TopNAggregationMetadataRegistry(checkNotNull(this.channel)); + return registry.delete(group, name); + } + + /** + * Delete the IndexRule + * @param group the group name of the index rule + * @param name the name of the index rule + * @return true if the index rule is deleted successfully + */ + public boolean deleteIndexRule(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + IndexRuleMetadataRegistry registry = new IndexRuleMetadataRegistry(checkNotNull(this.channel)); + return registry.delete(group, name); + } + + /** + * Delete the IndexRuleBinding + * @param group the group name of the index rule binding + * @param name the name of the index rule binding + * @return true if the index rule binding is deleted successfully + */ + public boolean deleteIndexRuleBinding(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + IndexRuleBindingMetadataRegistry registry = new IndexRuleBindingMetadataRegistry(checkNotNull(this.channel)); + return registry.delete(group, name); + } + + /** + * Find the IndexRule + * @param group the group name of the index rule + * @param name the name of the index rule + * @return the index rule if it can be found, otherwise null + */ + public IndexRule findIndexRule(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + IndexRuleMetadataRegistry registry = new IndexRuleMetadataRegistry(checkNotNull(this.channel)); + try { + return registry.get(group, name); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return null; + } + throw ex; + } + } + + /** + * Find all IndexRules in the group + * @param group the group name of the index rule + * @return all index rules in the group + */ + public List findIndexRules(String group) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + IndexRuleMetadataRegistry registry = new IndexRuleMetadataRegistry(checkNotNull(this.channel)); + return registry.list(group); + } + + /** + * Find the IndexRuleBinding + * @param group the group name of the index rule binding + * @param name the name of the index rule binding + * @return the index rule binding if it can be found, otherwise null + */ + public IndexRuleBinding findIndexRuleBinding(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + IndexRuleBindingMetadataRegistry registry = new IndexRuleBindingMetadataRegistry(checkNotNull(this.channel)); + try { + return registry.get(group, name); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return null; + } + throw ex; + } + } + + /** + * Find all IndexRuleBindings in the group + * @param group the group name of the index rule binding + * @return all index rule bindings in the group + */ + public List findIndexRuleBindings(String group) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + IndexRuleBindingMetadataRegistry registry = new IndexRuleBindingMetadataRegistry(checkNotNull(this.channel)); + return registry.list(group); + } + + /** + * Define a new property. + * + * @param property the property to be stored in the BanyanBD + * @throws BanyanDBException if the property is invalid + */ + public void define(org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Property property) throws BanyanDBException { + PropertyMetadataRegistry registry = new PropertyMetadataRegistry(checkNotNull(this.channel)); + registry.create(property); + } + + /** + * Update the property. + * + * @param property the property to be stored in the BanyanBD + * @throws BanyanDBException if the property is invalid + */ + public void update(org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Property property) throws BanyanDBException { + PropertyMetadataRegistry registry = new PropertyMetadataRegistry(checkNotNull(this.channel)); + registry.update(property); + } + + /** + * Find the property with given group and name + * + * @param group group of the metadata + * @param name name of the metadata + * @return the property found in BanyanDB. Otherwise, null is returned. + */ + public org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Property findPropertyDefinition(String group, String name) throws BanyanDBException { + PropertyMetadataRegistry registry = new PropertyMetadataRegistry(checkNotNull(this.channel)); + return registry.get(group, name); + } + + /** + * Find the properties with given group + * + * @param group group of the metadata + * @return the properties found in BanyanDB + */ + public List findPropertiesDefinition(String group) throws BanyanDBException { + PropertyMetadataRegistry registry = new PropertyMetadataRegistry(checkNotNull(this.channel)); + return registry.list(group); + } + + /** + * Delete the property + * + * @param group group of the metadata + * @param name name of the metadata + * @return if this property has been deleted + */ + public boolean deletePropertyDefinition(String group, String name) throws BanyanDBException { + PropertyMetadataRegistry registry = new PropertyMetadataRegistry(checkNotNull(this.channel)); + return registry.delete(group, name); + } + + /** + * Query properties + * + * @param request query request + * @return query response + */ + public BanyandbProperty.QueryResponse query(BanyandbProperty.QueryRequest request) throws BanyanDBException { + PropertyStore store = new PropertyStore(checkNotNull(this.channel)); + return store.query(request); + } + + /** + * Define a new trace + * + * @param trace the trace to be stored in the BanyanDB + * @throws BanyanDBException if the trace is invalid + */ + public void define(Trace trace) throws BanyanDBException { + TraceMetadataRegistry registry = new TraceMetadataRegistry(checkNotNull(this.channel)); + registry.create(trace); + } + + /** + * Update the trace. + * + * @param trace the trace to be stored in the BanyanDB + * @throws BanyanDBException if the trace is invalid + */ + public void update(Trace trace) throws BanyanDBException { + TraceMetadataRegistry registry = new TraceMetadataRegistry(checkNotNull(this.channel)); + registry.update(trace); + } + + /** + * Find the trace with given group and name + * + * @param group group of the metadata + * @param name name of the metadata + * @return the trace found in BanyanDB. Otherwise, null is returned. + */ + public Trace findTrace(String group, String name) throws BanyanDBException { + try { + return new TraceMetadataRegistry(checkNotNull(this.channel)).get(group, name); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return null; + } + throw ex; + } + } + + /** + * Find the traces with given group + * + * @param group group of the metadata + * @return the traces found in BanyanDB + */ + public List findTraces(String group) throws BanyanDBException { + TraceMetadataRegistry registry = new TraceMetadataRegistry(checkNotNull(this.channel)); + return registry.list(group); + } + + /** + * Delete the trace + * + * @param group group of the metadata + * @param name name of the metadata + * @return if this trace has been deleted + */ + public boolean deleteTrace(String group, String name) throws BanyanDBException { + TraceMetadataRegistry registry = new TraceMetadataRegistry(checkNotNull(this.channel)); + return registry.delete(group, name); + } + + /** + * Try to find the group defined + * + * @param name name of the group + * @return the group found in BanyanDB. Otherwise, null is returned. + */ + public Group findGroup(String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + + try { + return new GroupMetadataRegistry(checkNotNull(this.channel)).get(name, name); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return null; + } + throw ex; + } + } + + /** + * Try to find the groups defined + * + * @return the groups found in BanyanDB + */ + public List findGroups() throws BanyanDBException { + return new GroupMetadataRegistry(checkNotNull(this.channel)).list(""); + } + + /** + * Try to find the TopNAggregation from the BanyanDB with given group and name. + * + * @param group group of the TopNAggregation + * @param name name of the TopNAggregation + * @return TopNAggregation if found. Otherwise, null is returned. + */ + public TopNAggregation findTopNAggregation(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + try { + return new TopNAggregationMetadataRegistry(checkNotNull(this.channel)).get(group, name); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return null; + } + throw ex; + } + } + + /** + * Try to find the TopNAggregations from the BanyanDB with given group. + * + * @param group group of the TopNAggregations + * @return TopNAggregations if found. + */ + public List findTopNAggregations(String group) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + return new TopNAggregationMetadataRegistry(checkNotNull(this.channel)).list(group); + } + + /** + * Try to find the stream from the BanyanDB with given group and name. + * + * @param group group of the stream + * @param name name of the stream + * @return Steam if found. Otherwise, null is returned. + */ + public Stream findStream(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + try { + return new StreamMetadataRegistry(checkNotNull(this.channel)).get(group, name); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return null; + } + throw ex; + } + } + + /** + * Try to find the streams from the BanyanDB with given group. + * + * @param group group of the streams + * @return Streams if found. + */ + public List findStreams(String group) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + StreamMetadataRegistry registry = new StreamMetadataRegistry(checkNotNull(this.channel)); + return registry.list(group); + } + + /** + * Try to find the measure from the BanyanDB with given group and name. + * + * @param group group of the measure + * @param name name of the measure + * @return Measure with index rules if found. Otherwise, null is returned. + */ + public Measure findMeasure(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + try { + return new MeasureMetadataRegistry(checkNotNull(this.channel)).get(group, name); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return null; + } + throw ex; + } + } + + /** + * Try to find the measures from the BanyanDB with given group. + * + * @param group group of the measures + * @return Measures if found. + */ + public List findMeasures(String group) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + MeasureMetadataRegistry registry = new MeasureMetadataRegistry(checkNotNull(this.channel)); + return registry.list(group); + } + + private List findIndexRulesByGroupAndBindingName(String group, String bindingName) throws + BanyanDBException { + IndexRuleBindingMetadataRegistry irbRegistry = new IndexRuleBindingMetadataRegistry(checkNotNull(this.channel)); + + IndexRuleBinding irb; + try { + irb = irbRegistry.get(group, bindingName); + } catch (BanyanDBException ex) { + if (ex.getStatus().equals(Status.Code.NOT_FOUND)) { + return Collections.emptyList(); + } + throw ex; + } + + if (irb == null) { + return Collections.emptyList(); + } + + List indexRules = new ArrayList<>(irb.getRulesList().size()); + return indexRules; + } + + /** + * Check if the given stream exists. + * + * @param group group of the stream + * @param name name of the stream + * @return ResourceExist which indicates whether group and stream exist + */ + public ResourceExist existStream(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + + return new StreamMetadataRegistry(checkNotNull(this.channel)).exist(group, name); + } + + /** + * Check if the given measure exists. + * + * @param group group of the measure + * @param name name of the measure + * @return ResourceExist which indicates whether group and measure exist + */ + public ResourceExist existMeasure(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + + return new MeasureMetadataRegistry(checkNotNull(this.channel)).exist(group, name); + } + + /** + * Check if the given TopNAggregation exists. + * + * @param group group of the TopNAggregation + * @param name name of the TopNAggregation + * @return ResourceExist which indicates whether group and TopNAggregation exist + */ + public ResourceExist existTopNAggregation(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + + return new TopNAggregationMetadataRegistry(checkNotNull(this.channel)).exist(group, name); + } + + /** + * Check if the given property exists. + * + * @param group group of the property + * @param name name of the property + * @return ResourceExist which indicates whether group and property exist + */ + public ResourceExist existProperty(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + + return new PropertyMetadataRegistry(checkNotNull(this.channel)).exist(group, name); + } + + /** + * Check whether the trace definition is existed in the server + * + * @param group group of the metadata + * @param name name of the metadata + * @return ResourceExist which indicates whether group and trace exist + */ + public ResourceExist existTrace(String group, String name) throws BanyanDBException { + Preconditions.checkArgument(!Strings.isNullOrEmpty(group)); + Preconditions.checkArgument(!Strings.isNullOrEmpty(name)); + + return new TraceMetadataRegistry(checkNotNull(this.channel)).exist(group, name); + } + + /** + * Get the API version of the server + * + * @return the API version of the server + * @throws BanyanDBException if the server is not reachable + */ + public BanyandbCommon.APIVersion getAPIVersion() throws BanyanDBException { + ServiceGrpc.ServiceBlockingStub stub = ServiceGrpc.newBlockingStub(this.channel); + return HandleExceptionsWith.callAndTranslateApiException(() -> { + BanyandbCommon.GetAPIVersionResponse resp = stub.getAPIVersion(BanyandbCommon.GetAPIVersionRequest.getDefaultInstance()); + return resp.getVersion(); + }); + } + + @Override + public void close() throws IOException { + connectionEstablishLock.lock(); + if (!(this.channel instanceof ManagedChannel)) { + return; + } + final ManagedChannel managedChannel = (ManagedChannel) this.channel; + try { + if (isConnected) { + managedChannel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + isConnected = false; + } + } catch (InterruptedException interruptedException) { + Thread.currentThread().interrupt(); + log.warn("fail to wait for channel termination, shutdown now!", interruptedException); + managedChannel.shutdownNow(); + isConnected = false; + } finally { + connectionEstablishLock.unlock(); + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/DataPoint.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/DataPoint.java new file mode 100644 index 000000000000..f07c615ed4f6 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/DataPoint.java @@ -0,0 +1,66 @@ +/* + * 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.library.banyandb.v1.client; + +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +/** + * RowEntity represents an entity of BanyanDB entity. + */ +@Getter +public class DataPoint extends RowEntity { + private final Map fields; + + public static DataPoint create(BanyandbMeasure.DataPoint dataPoint) { + return new DataPoint(dataPoint); + } + + private DataPoint(BanyandbMeasure.DataPoint dataPoint) { + super(dataPoint.getTimestamp(), dataPoint.getTagFamiliesList()); + this.fields = new HashMap<>(dataPoint.getFieldsCount()); + for (BanyandbMeasure.DataPoint.Field f : dataPoint.getFieldsList()) { + this.fields.put(f.getName(), convertFileValueToJavaType(f.getValue())); + } + } + + public T getFieldValue(String fieldName) { + return (T) this.fields.get(fieldName); + } + + static Object convertFileValueToJavaType(BanyandbModel.FieldValue fieldValue) { + switch (fieldValue.getValueCase()) { + case INT: + return fieldValue.getInt().getValue(); + case STR: + return fieldValue.getStr().getValue(); + case NULL: + return null; + case BINARY_DATA: + return fieldValue.getBinaryData().toByteArray(); + case FLOAT: + return fieldValue.getFloat().getValue(); + default: + throw new IllegalStateException("illegal type of FieldValue"); + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Element.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Element.java new file mode 100644 index 000000000000..00a4c9f295ee --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Element.java @@ -0,0 +1,43 @@ +/* + * 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.library.banyandb.v1.client; + +import lombok.Getter; +import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; + +/** + * Element represents an entity in a Stream. + */ +@Getter +public class Element extends RowEntity { + /** + * identity of the element. + * For a trace entity, it is the spanID of a Span or the segmentId of a segment in Skywalking, + */ + protected final String id; + + public static Element create(BanyandbStream.Element element) { + return new Element(element); + } + + private Element(BanyandbStream.Element element) { + super(element.getTimestamp(), element.getTagFamiliesList()); + this.id = element.getElementId(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureQuery.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureQuery.java new file mode 100644 index 000000000000..5b0251c34996 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureQuery.java @@ -0,0 +1,238 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; +import java.util.List; +import java.util.Map; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +/** + * MeasureQuery is the high-level query API for the measure model. + */ +@Setter +public class MeasureQuery extends AbstractQuery { + /** + * field_projection can be used to select fields of the data points in the response + */ + private final Set fieldProjections; + + private Aggregation aggregation; + + private TopN topN; + + private Integer limit; + + private int offset; + + private OrderBy orderBy; + + private Set stages; + + public MeasureQuery(final List groups, + final String name, + final Map tagProjections, + final Set fieldProjections) { + this(groups, name, null, tagProjections, fieldProjections); + } + + public MeasureQuery(final List groups, + final String name, + final TimestampRange timestampRange, + final Map tagProjections, + final Set fieldProjections) { + super(groups, name, timestampRange, tagProjections); + this.fieldProjections = fieldProjections; + } + + @Override + public MeasureQuery and(PairQueryCondition condition) { + return (MeasureQuery) super.and(condition); + } + + @Override + public MeasureQuery or(PairQueryCondition condition) { + return (MeasureQuery) super.or(condition); + } + + public MeasureQuery groupBy(Set groupByKeys) { + Preconditions.checkArgument(tagProjections.keySet().containsAll(groupByKeys), "groupBy tags should be selected first"); + this.aggregation = new Aggregation(null, Aggregation.Type.UNSPECIFIED, groupByKeys); + return this; + } + + public MeasureQuery maxBy(String field, Set groupByKeys) { + Preconditions.checkArgument(fieldProjections.contains(field), "field should be selected first"); + Preconditions.checkArgument(tagProjections.keySet().containsAll(groupByKeys), "groupBy tags should be selected first"); + this.aggregation = new Aggregation(field, Aggregation.Type.MAX, groupByKeys); + return this; + } + + public MeasureQuery minBy(String field, Set groupByKeys) { + Preconditions.checkArgument(fieldProjections.contains(field), "field should be selected first"); + Preconditions.checkArgument(tagProjections.keySet().containsAll(groupByKeys), "groupBy tags should be selected first"); + Preconditions.checkState(this.aggregation == null, "aggregation should only be set once"); + this.aggregation = new Aggregation(field, Aggregation.Type.MIN, groupByKeys); + return this; + } + + public MeasureQuery meanBy(String field, Set groupByKeys) { + Preconditions.checkArgument(fieldProjections.contains(field), "field should be selected first"); + Preconditions.checkArgument(tagProjections.keySet().containsAll(groupByKeys), "groupBy tags should be selected first"); + Preconditions.checkState(this.aggregation == null, "aggregation should only be set once"); + this.aggregation = new Aggregation(field, Aggregation.Type.MEAN, groupByKeys); + return this; + } + + public MeasureQuery countBy(String field, Set groupByKeys) { + Preconditions.checkArgument(fieldProjections.contains(field), "field should be selected first"); + Preconditions.checkArgument(tagProjections.keySet().containsAll(groupByKeys), "groupBy tags should be selected first"); + Preconditions.checkState(this.aggregation == null, "aggregation should only be set once"); + this.aggregation = new Aggregation(field, Aggregation.Type.COUNT, groupByKeys); + return this; + } + + public MeasureQuery sumBy(String field, Set groupByKeys) { + Preconditions.checkArgument(fieldProjections.contains(field), "field should be selected first"); + Preconditions.checkArgument(tagProjections.keySet().containsAll(groupByKeys), "groupBy tags should be selected first"); + Preconditions.checkState(this.aggregation == null, "aggregation should only be set once"); + this.aggregation = new Aggregation(field, Aggregation.Type.SUM, groupByKeys); + return this; + } + + public MeasureQuery topN(int number, String field) { + Preconditions.checkArgument(fieldProjections.contains(field), "field should be selected first"); + this.topN = new TopN(field, number, Sort.DESC); + return this; + } + + public MeasureQuery bottomN(int number, String field) { + Preconditions.checkArgument(fieldProjections.contains(field), "field should be selected first"); + this.topN = new TopN(field, number, Sort.ASC); + return this; + } + + public MeasureQuery limit(int limit) { + this.limit = limit; + return this; + } + + public MeasureQuery offset(int offset) { + this.offset = offset; + return this; + } + + public MeasureQuery stages(Set stages) { + this.stages = stages; + return this; + } + + /** + * @return QueryRequest for gRPC level query. + */ + @Override + BanyandbMeasure.QueryRequest build() throws BanyanDBException { + final BanyandbMeasure.QueryRequest.Builder builder = BanyandbMeasure.QueryRequest.newBuilder(); + builder.setName(this.name); + builder.addAllGroups(this.groups); + if (timestampRange != null) { + builder.setTimeRange(timestampRange.build()); + } else { + builder.setTimeRange(TimestampRange.MAX_RANGE); + } + BanyandbModel.TagProjection tagProjections = buildTagProjections(); + if (tagProjections.getTagFamiliesCount() > 0) { + builder.setTagProjection(buildTagProjections()); + } + if (!fieldProjections.isEmpty()) { + builder.setFieldProjection(BanyandbMeasure.QueryRequest.FieldProjection.newBuilder() + .addAllNames(fieldProjections) + .build()); + } + if (stages != null && !stages.isEmpty()) { + builder.addAllStages(stages); + } + if (this.aggregation != null) { + BanyandbMeasure.QueryRequest.GroupBy.Builder groupByBuilder = BanyandbMeasure.QueryRequest.GroupBy.newBuilder() + .setTagProjection(buildTagProjections(this.aggregation.groupByTagsProjection)); + if (Strings.isNullOrEmpty(this.aggregation.fieldName)) { + if (this.aggregation.aggregationType != Aggregation.Type.UNSPECIFIED) { + throw new IllegalArgumentException("field name cannot be null or empty if aggregation is specified"); + } + } else { + groupByBuilder.setFieldName(this.aggregation.fieldName); + BanyandbMeasure.QueryRequest.Aggregation aggr = BanyandbMeasure.QueryRequest.Aggregation.newBuilder() + .setFunction(this.aggregation.aggregationType.function) + .setFieldName(this.aggregation.fieldName) + .build(); + builder.setGroupBy(groupByBuilder.build()).setAgg(aggr); + } + } + if (this.topN != null) { + BanyandbMeasure.QueryRequest.Top top = BanyandbMeasure.QueryRequest.Top.newBuilder() + .setFieldName(this.topN.fieldName) + .setNumber(this.topN.number) + .setFieldValueSort(Sort.DESC.equals(this.topN.sort) ? BanyandbModel.Sort.SORT_DESC : BanyandbModel.Sort.SORT_ASC) + .build(); + builder.setTop(top); + } + builder.setOffset(this.offset); + if (this.limit != null) { + builder.setLimit(this.limit); + } + if (this.orderBy != null) { + builder.setOrderBy(orderBy.build()); + } + // add all criteria + buildCriteria().ifPresent(builder::setCriteria); + builder.setTrace(this.trace); + return builder.build(); + } + + @RequiredArgsConstructor + public static class TopN { + private final String fieldName; + private final int number; + private final AbstractQuery.Sort sort; + } + + @RequiredArgsConstructor + public static class Aggregation { + private final String fieldName; + private final Type aggregationType; + private final Set groupByTagsProjection; + + @RequiredArgsConstructor + public enum Type { + UNSPECIFIED(BanyandbModel.AggregationFunction.AGGREGATION_FUNCTION_UNSPECIFIED), + MEAN(BanyandbModel.AggregationFunction.AGGREGATION_FUNCTION_MEAN), + MAX(BanyandbModel.AggregationFunction.AGGREGATION_FUNCTION_MAX), + MIN(BanyandbModel.AggregationFunction.AGGREGATION_FUNCTION_MIN), + COUNT(BanyandbModel.AggregationFunction.AGGREGATION_FUNCTION_COUNT), + SUM(BanyandbModel.AggregationFunction.AGGREGATION_FUNCTION_SUM); + final BanyandbModel.AggregationFunction function; + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureQueryResponse.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureQueryResponse.java new file mode 100644 index 000000000000..fbc4c5d4dddd --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureQueryResponse.java @@ -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.library.banyandb.v1.client; + +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; + +/** + * MeasureQueryResponse represents the measure query result. + */ +public class MeasureQueryResponse { + @Getter + private final List dataPoints; + + @Getter + private final Trace trace; + + MeasureQueryResponse(BanyandbMeasure.QueryResponse response) { + final List dataPointList = response.getDataPointsList(); + this.dataPoints = new ArrayList<>(dataPointList.size()); + for (final BanyandbMeasure.DataPoint dp : dataPointList) { + dataPoints.add(DataPoint.create(dp)); + } + this.trace = Trace.convertFromProto(response.getTrace()); + } + + /** + * @return size of the response set. + */ + public int size() { + return dataPoints.size(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureWrite.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureWrite.java new file mode 100644 index 000000000000..477e21ef6501 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/MeasureWrite.java @@ -0,0 +1,153 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.protobuf.Timestamp; +import java.util.Map; +import java.util.TreeMap; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Serializable; + +public class MeasureWrite extends AbstractWrite { + + // Use TreeMap to have a consistent order for fields + private final Map/*fieldValue*/> fields; + + // Use TreeMap to have a consistent order for tags + private final Map/*tagValue*/>> tags; + + MeasureWrite(BanyandbCommon.Metadata entityMetadata, long timestamp) { + super(entityMetadata, timestamp); + this.fields = new TreeMap<>(); + this.tags = new TreeMap<>(); + } + + public MeasureWrite field(String fieldName, Serializable fieldVal) { + this.fields.put(fieldName, fieldVal); + return this; + } + + public MeasureWrite tag(String tagFamilyName, String tagName, Serializable tagValue) throws BanyanDBException { + this.tags.computeIfAbsent(tagFamilyName, k -> new TreeMap<>()).put(tagName, tagValue); + return this; + } + + /** + * Build a write request + * + * @return {@link BanyandbMeasure.WriteRequest} for the bulk process. + */ + @Override + protected BanyandbMeasure.WriteRequest build(BanyandbCommon.Metadata metadata) { + if (!timestamp.isPresent() || timestamp.get() <= 0) { + throw new IllegalArgumentException("Timestamp is required and must be greater than 0 for stream writes."); + } + Timestamp ts = Timestamp.newBuilder() + .setSeconds(timestamp.get() / 1000) + .setNanos((int) (timestamp.get() % 1000 * 1_000_000)).build(); + + final BanyandbMeasure.WriteRequest.Builder builder = BanyandbMeasure.WriteRequest.newBuilder(); + builder.setMetadata(metadata); + final BanyandbMeasure.DataPointValue.Builder datapointValueBuilder = BanyandbMeasure.DataPointValue.newBuilder(); + final BanyandbMeasure.DataPointSpec.Builder datapointValueSpecBuilder = BanyandbMeasure.DataPointSpec.newBuilder(); + datapointValueBuilder.setTimestamp(ts); + for (Map.Entry>> tagFamilyEntry : this.tags.entrySet()) { + BanyandbMeasure.TagFamilySpec.Builder tagFamilySpecBuilder = BanyandbMeasure.TagFamilySpec.newBuilder(); + BanyandbModel.TagFamilyForWrite.Builder tagFamilyForWriteBuilder = BanyandbModel.TagFamilyForWrite.newBuilder(); + tagFamilySpecBuilder.setName(tagFamilyEntry.getKey()); + for (Map.Entry> tagEntry : tagFamilyEntry.getValue().entrySet()) { + tagFamilySpecBuilder.addTagNames(tagEntry.getKey()); + tagFamilyForWriteBuilder.addTags(tagEntry.getValue().serialize()); + } + datapointValueSpecBuilder.addTagFamilySpec(tagFamilySpecBuilder); + datapointValueBuilder.addTagFamilies(tagFamilyForWriteBuilder); + } + + for (Map.Entry> fieldEntry : this.fields.entrySet()) { + datapointValueSpecBuilder.addFieldNames(fieldEntry.getKey()); + datapointValueBuilder.addFields(fieldEntry.getValue().serialize()); + } + + builder.setDataPointSpec(datapointValueSpecBuilder); + builder.setDataPoint(datapointValueBuilder); + builder.setMessageId(System.nanoTime()); + return builder.build(); + } + + /** + * Build a write request without metadata and tag specs. + * + * @return {@link BanyandbMeasure.WriteRequest} for the bulk process. + */ + @Override + protected BanyandbMeasure.WriteRequest buildValues() { + if (!timestamp.isPresent() || timestamp.get() <= 0) { + throw new IllegalArgumentException("Timestamp is required and must be greater than 0 for stream writes."); + } + Timestamp ts = Timestamp.newBuilder() + .setSeconds(timestamp.get() / 1000) + .setNanos((int) (timestamp.get() % 1000 * 1_000_000)).build(); + + final BanyandbMeasure.WriteRequest.Builder builder = BanyandbMeasure.WriteRequest.newBuilder(); + final BanyandbMeasure.DataPointValue.Builder datapointValueBuilder = BanyandbMeasure.DataPointValue.newBuilder(); + datapointValueBuilder.setTimestamp(ts); + for (Map.Entry>> tagFamilyEntry : this.tags.entrySet()) { + BanyandbModel.TagFamilyForWrite.Builder tagFamilyForWriteBuilder = BanyandbModel.TagFamilyForWrite.newBuilder(); + for (Map.Entry> tagEntry : tagFamilyEntry.getValue().entrySet()) { + tagFamilyForWriteBuilder.addTags(tagEntry.getValue().serialize()); + } + datapointValueBuilder.addTagFamilies(tagFamilyForWriteBuilder); + } + + for (Map.Entry> fieldEntry : this.fields.entrySet()) { + datapointValueBuilder.addFields(fieldEntry.getValue().serialize()); + } + + builder.setDataPoint(datapointValueBuilder); + builder.setMessageId(System.nanoTime()); + return builder.build(); + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("group=").append(entityMetadata.getGroup()).append(", ").append("name=") + .append(entityMetadata.getName()).append(", ").append("timestamp=").append(timestamp).append(", "); + for (Map.Entry>> entry : tags.entrySet()) { + String tagFamilyName = entry.getKey(); + Map> tagMap = entry.getValue(); + for (Map.Entry> tagEntry : tagMap.entrySet()) { + String tagName = tagEntry.getKey(); + Serializable tagValue = tagEntry.getValue(); + stringBuilder.append(tagFamilyName).append(".").append(tagName).append("=") + .append(tagValue.serialize()).append(", "); + } + } + for (Map.Entry> fieldEntry : fields.entrySet()) { + String fieldName = fieldEntry.getKey(); + Serializable fieldValue = fieldEntry.getValue(); + stringBuilder.append("field.").append(fieldName).append("=") + .append(fieldValue.serialize()).append(", "); + } + return stringBuilder.toString(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Options.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Options.java new file mode 100644 index 000000000000..76f89cba836b --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Options.java @@ -0,0 +1,86 @@ +/* + * 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.library.banyandb.v1.client; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import org.apache.skywalking.library.banyandb.v1.client.grpc.channel.ChannelManagerSettings; + +/** + * Client connection options. + */ +@Setter(AccessLevel.PUBLIC) +@Getter(AccessLevel.PUBLIC) +public class Options { + /** + * Max inbound message size + */ + private int maxInboundMessageSize = 1024 * 1024 * 50; + /** + * Threshold of gRPC blocking query, unit is second + */ + private int deadline = 30; + /** + * Refresh interval for the gRPC channel, unit is second + */ + private long refreshInterval = 30; + /** + * Threshold of force gRPC reconnection if network issue is encountered + */ + private long forceReconnectionThreshold = 1; + + /** + * Force use TLS for gRPC + * Default is false + */ + private boolean forceTLS = false; + /** + * SSL: Trusted CA Path + */ + private String sslTrustCAPath = ""; + /** + * Basic Auth: username of BanyanDB server + */ + private String username = ""; + /** + * Basic Auth: password of BanyanDB server + */ + private String password = ""; + /** + * Enable Prometheus metrics + */ + private PrometheusMetricsOpts prometheusMetricsOpts = new PrometheusMetricsOpts(); + + public Options() { + } + + ChannelManagerSettings buildChannelManagerSettings() { + return ChannelManagerSettings.builder() + .refreshInterval(this.refreshInterval) + .forceReconnectionThreshold(this.forceReconnectionThreshold) + .build(); + } + + public static class PrometheusMetricsOpts { + @Setter(AccessLevel.PUBLIC) + @Getter + private String clientID = "default"; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Or.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Or.java new file mode 100644 index 000000000000..32806b8e512f --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Or.java @@ -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.library.banyandb.v1.client; + +import lombok.Builder; +import lombok.Getter; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +@Builder +@Getter +public class Or extends LogicalExpression { + private final AbstractCriteria left; + private final AbstractCriteria right; + + @Override + public BanyandbModel.Criteria build() { + return BanyandbModel.Criteria.newBuilder() + .setLe(BanyandbModel.LogicalExpression.newBuilder() + .setLeft(left.build()) + .setRight(right.build()) + .setOp(BanyandbModel.LogicalExpression.LogicalOp.LOGICAL_OP_OR) + .build()) + .build(); + } + + public static Or create(AbstractCriteria left, AbstractCriteria right) { + return Or.builder().left(left).right(right).build(); + } + + @Override + AbstractCriteria left() { + return left; + } + + @Override + AbstractCriteria right() { + return right; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PairQueryCondition.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PairQueryCondition.java new file mode 100644 index 000000000000..df843bbee4e2 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PairQueryCondition.java @@ -0,0 +1,350 @@ +/* + * 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.library.banyandb.v1.client; + +import java.util.List; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel.Condition.MatchOption; + +/** + * PairQuery represents a query condition, including tag name, operator, and value(s); + */ +public abstract class PairQueryCondition extends AbstractCriteria { + protected final BanyandbModel.Condition.BinaryOp op; + private final TagAndValue tagAndValue; + private final MatchOption matchOption; + + private PairQueryCondition(BanyandbModel.Condition.BinaryOp op, TagAndValue tagAndValue) { + this.op = op; + this.tagAndValue = tagAndValue; + this.matchOption = MatchOption.getDefaultInstance(); + } + + private PairQueryCondition(BanyandbModel.Condition.BinaryOp op, + TagAndValue tagAndValue, + MatchOption matchOption) { + this.op = op; + this.tagAndValue = tagAndValue; + this.matchOption = matchOption; + } + + @Override + public BanyandbModel.Criteria build() { + BanyandbModel.Condition.Builder condition = BanyandbModel.Condition.newBuilder() + .setName(this.tagAndValue.getTagName()) + .setOp(this.op) + .setValue(this.tagAndValue.buildTypedTagValue()); + if (this.matchOption != null) { + condition.setMatchOption(this.matchOption); + } + return BanyandbModel.Criteria.newBuilder() + .setCondition(condition.build()) + .build(); + } + + public String getTagName() { + return this.tagAndValue.getTagName(); + } + + /** + * LongQueryCondition represents `tag(Long) $op value` condition. + */ + public static class LongQueryCondition extends PairQueryCondition { + private LongQueryCondition(String tagName, BanyandbModel.Condition.BinaryOp op, Long value) { + super(op, new TagAndValue.LongTagPair(tagName, value)); + } + + /** + * Build a query condition for {@link Long} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_EQ} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `Long == value` + */ + public static PairQueryCondition eq(String tagName, Long val) { + return new LongQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_EQ, val); + } + + /** + * Build a query condition for {@link Long} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_NE} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `Long != value` + */ + public static PairQueryCondition ne(String tagName, Long val) { + return new LongQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_NE, val); + } + + /** + * Build a query condition for {@link Long} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_GT} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `Long > value` + */ + public static PairQueryCondition gt(String tagName, Long val) { + return new LongQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_GT, val); + } + + /** + * Build a query condition for {@link Long} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_GE} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `Long ≥ value` + */ + public static PairQueryCondition ge(String tagName, Long val) { + return new LongQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_GE, val); + } + + /** + * Build a query condition for {@link Long} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_LT} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `Long < value` + */ + public static PairQueryCondition lt(String tagName, Long val) { + return new LongQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_LT, val); + } + + /** + * Build a query condition for {@link Long} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_LE} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `Long ≤ value` + */ + public static PairQueryCondition le(String tagName, Long val) { + return new LongQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_LE, val); + } + + } + + /** + * StringQueryCondition represents `tag(String) $op value` condition. + */ + public static class StringQueryCondition extends PairQueryCondition { + private StringQueryCondition(String tagName, BanyandbModel.Condition.BinaryOp op, String value) { + super(op, new TagAndValue.StringTagPair(tagName, value)); + } + + private StringQueryCondition(String tagName, BanyandbModel.Condition.BinaryOp op, String value, MatchOption matchOption) { + super(op, new TagAndValue.StringTagPair(tagName, value), matchOption); + } + + /** + * Build a query condition for {@link String} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_EQ} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `String == value` + */ + public static PairQueryCondition eq(String tagName, String val) { + return new StringQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_EQ, val); + } + + /** + * Build a query condition for {@link String} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_NE} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `String != value` + */ + public static PairQueryCondition ne(String tagName, String val) { + return new StringQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_NE, val); + } + + /** + * Build a query condition for {@link String} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_MATCH} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `String match value` + */ + public static PairQueryCondition match(String tagName, String val) { + return new StringQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_MATCH, val); + } + + /** + * Build a query condition for {@link String} type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_MATCH} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @param matchOption set the specific match options + * @return a query that `match value` + */ + public static PairQueryCondition match(String tagName, String val, MatchOption matchOption) { + return new StringQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_MATCH, val, matchOption); + } + } + + /** + * StringArrayQueryCondition represents `tag(List of String) $op value` condition. + */ + public static class StringArrayQueryCondition extends PairQueryCondition> { + private StringArrayQueryCondition(String tagName, BanyandbModel.Condition.BinaryOp op, List value) { + super(op, new TagAndValue.StringArrayTagPair(tagName, value)); + } + + /** + * Build a query condition for {@link List} of {@link String} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_EQ} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[String] == values` + */ + public static PairQueryCondition> eq(String tagName, List val) { + return new StringArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_EQ, val); + } + + /** + * Build a query condition for {@link List} of {@link String} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_NE} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[String] != values` + */ + public static PairQueryCondition> ne(String tagName, List val) { + return new StringArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_NE, val); + } + + /** + * Build a query condition for {@link List} of {@link String} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_HAVING} as the relation, + * i.e. val is a subset. + * + * @param tagName name of the tag + * @param val value of the tag, a subset of the tagName's value + * @return a query that `[String] having values` + */ + public static PairQueryCondition> having(String tagName, List val) { + return new StringArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_HAVING, val); + } + + /** + * Build a query condition for {@link List} of {@link String} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_NOT_HAVING} as the relation, + * i.e. val is not a subset. + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[String] not having values` + */ + public static PairQueryCondition> notHaving(String tagName, List val) { + return new StringArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_NOT_HAVING, val); + } + + /** + * Build a query condition for {@link List} of {@link String} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_IN} as the relation, + * i.e. intersection of the val and the stored tagName's value must not be empty. + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[String] in values` + */ + public static PairQueryCondition> in(String tagName, List val) { + return new StringArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_IN, val); + } + + /** + * Build a query condition for {@link List} of {@link String} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_NOT_IN} as the relation, + * i.e. intersection of the val and the stored tagName's value must be empty. + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[String] not in values` + */ + public static PairQueryCondition> notIn(String tagName, List val) { + return new StringArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_NOT_IN, val); + } + } + + /** + * LongArrayQueryCondition represents `tag(List of Long) $op value` condition. + */ + public static class LongArrayQueryCondition extends PairQueryCondition> { + private LongArrayQueryCondition(String tagName, BanyandbModel.Condition.BinaryOp op, List value) { + super(op, new TagAndValue.LongArrayTagPair(tagName, value)); + } + + /** + * Build a query condition for {@link List} of {@link Long} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_EQ} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[Long] == value` + */ + public static PairQueryCondition> eq(String tagName, List val) { + return new LongArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_EQ, val); + } + + /** + * Build a query condition for {@link List} of {@link Long} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_NE} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[Long] != value` + */ + public static PairQueryCondition> ne(String tagName, List val) { + return new LongArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_NE, val); + } + + /** + * Build a query condition for {@link List} of {@link Long} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_HAVING} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[Long] having values` + */ + public static PairQueryCondition> having(String tagName, List val) { + return new LongArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_HAVING, val); + } + + /** + * Build a query condition for {@link List} of {@link Long} as the type + * and {@link BanyandbModel.Condition.BinaryOp#BINARY_OP_NOT_HAVING} as the relation + * + * @param tagName name of the tag + * @param val value of the tag + * @return a query that `[Long] not having values` + */ + public static PairQueryCondition> notHaving(String tagName, List val) { + return new LongArrayQueryCondition(tagName, BanyandbModel.Condition.BinaryOp.BINARY_OP_NOT_HAVING, val); + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PropertyQuery.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PropertyQuery.java new file mode 100644 index 000000000000..73e448eb6a66 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PropertyQuery.java @@ -0,0 +1,101 @@ +/* + * 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.library.banyandb.v1.client; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import lombok.Setter; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +/** + * PropertyQuery is the high-level query API for the property model. + */ +@Setter +public class PropertyQuery extends AbstractQuery { + /** + * The limit size of the query. Default value is 20. + */ + private int limit; + + /** + * Specific property IDs to query + */ + private List ids; + + /** + * Construct a property query with required fields + */ + public PropertyQuery(final List groups, final String name, final Set projections) { + super(groups, name, null, projections); + this.limit = 20; + this.ids = new ArrayList<>(); + } + + /** + * Add a property ID to filter query results + * @param id property ID + * @return this query instance for chaining + */ + public PropertyQuery id(String id) { + if (id != null && !id.isEmpty()) { + this.ids.add(id); + } + return this; + } + + /** + * Add multiple property IDs to filter query results + * @param ids list of property IDs + * @return this query instance for chaining + */ + public PropertyQuery ids(List ids) { + if (ids != null) { + this.ids.addAll(ids); + } + return this; + } + + @Override + public PropertyQuery and(PairQueryCondition condition) { + return (PropertyQuery) super.and(condition); + } + + @Override + public PropertyQuery or(PairQueryCondition condition) { + return (PropertyQuery) super.or(condition); + } + + public BanyandbProperty.QueryRequest build() throws BanyanDBException { + final BanyandbProperty.QueryRequest.Builder builder = BanyandbProperty.QueryRequest.newBuilder(); + builder.setName(this.name); + builder.addAllGroups(this.groups); + builder.addAllTagProjection(this.tagProjections.keySet()); + buildCriteria().ifPresent(builder::setCriteria); + builder.setLimit(this.limit); + builder.setTrace(this.trace); + + if (!this.ids.isEmpty()) { + builder.addAllIds(this.ids); + } + + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PropertyStore.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PropertyStore.java new file mode 100644 index 000000000000..e9b9b89747d4 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/PropertyStore.java @@ -0,0 +1,66 @@ +/* + * 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.library.banyandb.v1.client; + +import io.grpc.Channel; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.ApplyRequest; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.ApplyRequest.Strategy; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.ApplyResponse; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.DeleteResponse; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.Property; +import org.apache.skywalking.banyandb.property.v1.PropertyServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.HandleExceptionsWith; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class PropertyStore { + private final PropertyServiceGrpc.PropertyServiceBlockingStub stub; + + public PropertyStore(Channel channel) { + this.stub = PropertyServiceGrpc.newBlockingStub(channel); + } + + public ApplyResponse apply(Property payload) throws BanyanDBException { + return apply(payload, Strategy.STRATEGY_MERGE); + } + + public ApplyResponse apply(Property payload, Strategy strategy) throws BanyanDBException { + Strategy s = Strategy.STRATEGY_MERGE; + ApplyRequest r = ApplyRequest.newBuilder() + .setProperty(payload) + .setStrategy(strategy) + .build(); + return HandleExceptionsWith.callAndTranslateApiException(() -> + this.stub.apply(r)); + } + + public DeleteResponse delete(String group, String name, String id) throws BanyanDBException { + return HandleExceptionsWith.callAndTranslateApiException(() -> + this.stub.delete(BanyandbProperty.DeleteRequest.newBuilder() + .setGroup(group) + .setName(name) + .setId(id) + .build())); + } + + public BanyandbProperty.QueryResponse query(BanyandbProperty.QueryRequest req) throws BanyanDBException { + return HandleExceptionsWith.callAndTranslateApiException(() -> + this.stub.query(req)); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/RowEntity.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/RowEntity.java new file mode 100644 index 000000000000..266b3e4ca4de --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/RowEntity.java @@ -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.library.banyandb.v1.client; + +import com.google.protobuf.Timestamp; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +/** + * RowEntity represents an entity of BanyanDB. + */ +@Getter +public class RowEntity { + /** + * timestamp of the entity in the timeunit of milliseconds. + */ + protected final long timestamp; + + /** + * tags is a map maintaining the relation between tag name and its value, + * (in the format of Java Types converted from gRPC Types). + * The family name is thus ignored, since the name should be globally unique for a schema. + */ + protected final Map tags; + + protected RowEntity(Timestamp ts, List tagFamilyList) { + timestamp = ts.getSeconds() * 1000 + ts.getNanos() / 1_000_000; + this.tags = new HashMap<>(); + for (final BanyandbModel.TagFamily tagFamily : tagFamilyList) { + for (final BanyandbModel.Tag tag : tagFamily.getTagsList()) { + final Object val = convertToJavaType(tag.getValue()); + if (val != null) { + this.tags.put(tag.getKey(), val); + } + } + } + } + + public T getTagValue(String tagName) { + return (T) this.tags.get(tagName); + } + + private Object convertToJavaType(BanyandbModel.TagValue tagValue) { + switch (tagValue.getValueCase()) { + case INT: + return tagValue.getInt().getValue(); + case STR: + return tagValue.getStr().getValue(); + case NULL: + return null; + case INT_ARRAY: + return tagValue.getIntArray().getValueList(); + case STR_ARRAY: + return tagValue.getStrArray().getValueList(); + case BINARY_DATA: + return tagValue.getBinaryData().toByteArray(); + default: + throw new IllegalStateException("illegal type of TagValue"); + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Span.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Span.java new file mode 100644 index 000000000000..7f0b685561a6 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Span.java @@ -0,0 +1,57 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.protobuf.Timestamp; +import java.util.List; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +/** + * Span represents the span of a {@link Trace}. + */ +@Getter +@Setter(value = AccessLevel.PRIVATE) +public class Span { + private Timestamp startTime; + private Timestamp endTime; + private boolean error; + private List tags; + private String message; + private List children; + private long duration; + + static Span convertSpanFromProto(org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Span protoSpan) { + Span spanBean = new Span(); + spanBean.setStartTime(protoSpan.getStartTime()); + spanBean.setEndTime(protoSpan.getEndTime()); + spanBean.setError(protoSpan.getError()); + spanBean.setMessage(protoSpan.getMessage()); + spanBean.setDuration(protoSpan.getDuration()); + spanBean.setTags(protoSpan.getTagsList().stream() + .map(Tag::convertTagFromProto) + .collect(Collectors.toList())); + spanBean.setChildren(protoSpan.getChildrenList().stream() + .map(Span::convertSpanFromProto) + .collect(Collectors.toList())); + return spanBean; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamQuery.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamQuery.java new file mode 100644 index 000000000000..8e0950482db8 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamQuery.java @@ -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.library.banyandb.v1.client; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import lombok.Setter; +import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +/** + * StreamQuery is the high-level query API for the stream model. + */ +@Setter +public class StreamQuery extends AbstractQuery { + /** + * The starting row id of the query. Default value is 0. + */ + private int offset; + /** + * The limit size of the query. Default value is 20. + */ + private int limit; + /** + * One order condition is supported and optional. + */ + private OrderBy orderBy; + + /** + * The stages of the stream query. + */ + private Set stages; + + public StreamQuery(final List groups, + final String name, + final TimestampRange timestampRange, + final Map projections) { + super(groups, name, timestampRange, projections); + this.offset = 0; + this.limit = 20; + } + + public StreamQuery(final List groups, + final String name, + final Map projections) { + this(groups, name, null, projections); + } + + @Override + public StreamQuery and(PairQueryCondition condition) { + return (StreamQuery) super.and(condition); + } + + @Override + public StreamQuery or(PairQueryCondition condition) { + return (StreamQuery) super.or(condition); + } + + public StreamQuery stages(Set stages) { + this.stages = stages; + return this; + } + + @Override + BanyandbStream.QueryRequest build() throws BanyanDBException { + final BanyandbStream.QueryRequest.Builder builder = BanyandbStream.QueryRequest.newBuilder(); + builder.setName(this.name); + builder.addAllGroups(this.groups); + if (timestampRange != null) { + builder.setTimeRange(timestampRange.build()); + } + builder.setProjection(buildTagProjections()); + buildCriteria().ifPresent(builder::setCriteria); + builder.setOffset(offset); + builder.setLimit(limit); + if (orderBy != null) { + builder.setOrderBy(orderBy.build()); + } + if (stages != null && !stages.isEmpty()) { + builder.addAllStages(stages); + } + builder.setTrace(this.trace); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamQueryResponse.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamQueryResponse.java new file mode 100644 index 000000000000..adea6f6a0756 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamQueryResponse.java @@ -0,0 +1,49 @@ +/* + * 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.library.banyandb.v1.client; + +import java.util.ArrayList; +import java.util.List; +import lombok.Getter; +import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; + +/** + * StreamQueryResponse represents the stream query result. + */ +public class StreamQueryResponse { + @Getter + private final List elements; + + @Getter + private final Trace trace; + + StreamQueryResponse(BanyandbStream.QueryResponse response) { + final List elementsList = response.getElementsList(); + elements = new ArrayList<>(elementsList.size()); + elementsList.forEach(element -> elements.add(Element.create(element))); + this.trace = Trace.convertFromProto(response.getTrace()); + } + + /** + * @return size of the response set. + */ + public int size() { + return elements.size(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamWrite.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamWrite.java new file mode 100644 index 000000000000..91f80c0b1b51 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/StreamWrite.java @@ -0,0 +1,149 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.protobuf.Timestamp; +import java.util.Map; +import java.util.Optional; +import java.util.TreeMap; +import lombok.Getter; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Serializable; + +/** + * StreamWrite represents a write operation, including necessary fields. + */ +public class StreamWrite extends AbstractWrite { + /** + * ID of current entity + */ + @Getter + private final String elementId; + + // Use TreeMap to have a consistent order for tags + private final Map/*tagValue*/>> tags; + + /** + * Create a StreamWrite without initial timestamp. + */ + StreamWrite(BanyandbCommon.Metadata entityMetadata, final String elementId) { + super(entityMetadata); + this.elementId = elementId; + this.tags = new TreeMap<>(); + } + + public StreamWrite tag(String tagFamilyName, String tagName, Serializable tagValue) throws BanyanDBException { + this.tags.computeIfAbsent(tagFamilyName, k -> new TreeMap<>()).put(tagName, tagValue); + return this; + } + + public void setTimestamp(long timestamp) { + super.timestamp = Optional.of(timestamp); + } + + /** + * Build a write request + * + * @return {@link BanyandbStream.WriteRequest} for the bulk process. + */ + @Override + protected BanyandbStream.WriteRequest build(BanyandbCommon.Metadata metadata) { + if (!timestamp.isPresent() || timestamp.get() <= 0) { + throw new IllegalArgumentException("Timestamp is required and must be greater than 0 for stream writes."); + } + + Timestamp ts = Timestamp.newBuilder() + .setSeconds(timestamp.get() / 1000) + .setNanos((int) (timestamp.get() % 1000 * 1_000_000)).build(); + + final BanyandbStream.WriteRequest.Builder builder = BanyandbStream.WriteRequest.newBuilder(); + builder.setMetadata(metadata); + final BanyandbStream.ElementValue.Builder elemValBuilder = BanyandbStream.ElementValue.newBuilder(); + elemValBuilder.setElementId(elementId); + elemValBuilder.setTimestamp(ts); + for (Map.Entry>> tagFamilyEntry : this.tags.entrySet()) { + BanyandbStream.TagFamilySpec.Builder tagFamilySpecBuilder = BanyandbStream.TagFamilySpec.newBuilder(); + BanyandbModel.TagFamilyForWrite.Builder tagFamilyForWriteBuilder = BanyandbModel.TagFamilyForWrite.newBuilder(); + tagFamilySpecBuilder.setName(tagFamilyEntry.getKey()); + for (Map.Entry> tagEntry : tagFamilyEntry.getValue().entrySet()) { + tagFamilySpecBuilder.addTagNames(tagEntry.getKey()); + tagFamilyForWriteBuilder.addTags(tagEntry.getValue().serialize()); + } + builder.addTagFamilySpec(tagFamilySpecBuilder); + elemValBuilder.addTagFamilies(tagFamilyForWriteBuilder); + } + + builder.setElement(elemValBuilder); + builder.setMessageId(System.nanoTime()); + return builder.build(); + } + + /** + * Build a write request without metadata and tag specs. + * + * @return {@link BanyandbStream.WriteRequest} for the bulk process. + */ + @Override + protected BanyandbStream.WriteRequest buildValues() { + if (!timestamp.isPresent() || timestamp.get() <= 0) { + throw new IllegalArgumentException("Timestamp is required and must be greater than 0 for stream writes."); + } + + Timestamp ts = Timestamp.newBuilder() + .setSeconds(timestamp.get() / 1000) + .setNanos((int) (timestamp.get() % 1000 * 1_000_000)).build(); + + final BanyandbStream.WriteRequest.Builder builder = BanyandbStream.WriteRequest.newBuilder(); + final BanyandbStream.ElementValue.Builder elemValBuilder = BanyandbStream.ElementValue.newBuilder(); + elemValBuilder.setElementId(elementId); + elemValBuilder.setTimestamp(ts); + for (Map.Entry>> tagFamilyEntry : this.tags.entrySet()) { + BanyandbModel.TagFamilyForWrite.Builder tagFamilyForWriteBuilder = BanyandbModel.TagFamilyForWrite.newBuilder(); + for (Map.Entry> tagEntry : tagFamilyEntry.getValue().entrySet()) { + tagFamilyForWriteBuilder.addTags(tagEntry.getValue().serialize()); + } + elemValBuilder.addTagFamilies(tagFamilyForWriteBuilder); + } + + builder.setElement(elemValBuilder); + builder.setMessageId(System.nanoTime()); + return builder.build(); + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("group=").append(entityMetadata.getGroup()).append(", ").append("name=") + .append(entityMetadata.getName()).append(", ").append("timestamp=").append(timestamp).append(", "); + for (Map.Entry>> entry : tags.entrySet()) { + String tagFamilyName = entry.getKey(); + Map> tagMap = entry.getValue(); + for (Map.Entry> tagEntry : tagMap.entrySet()) { + String tagName = tagEntry.getKey(); + Serializable tagValue = tagEntry.getValue(); + stringBuilder.append(tagFamilyName).append(".").append(tagName).append("=") + .append(tagValue.serialize()).append(", "); + } + } + return stringBuilder.toString(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Tag.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Tag.java new file mode 100644 index 000000000000..2b41121e9984 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Tag.java @@ -0,0 +1,43 @@ +/* + * 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.library.banyandb.v1.client; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +/** + * Tag represents the key-value pair of a tag in a {@link Span}. + */ +@Getter +@Setter(value = AccessLevel.PRIVATE) +@ToString +public class Tag { + private String key; + private String value; + + static Tag convertTagFromProto(org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Tag protoTag) { + Tag tagBean = new Tag(); + tagBean.setKey(protoTag.getKey()); + tagBean.setValue(protoTag.getValue()); + return tagBean; + } +} + diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TagAndValue.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TagAndValue.java new file mode 100644 index 000000000000..73c79fd3c0fb --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TagAndValue.java @@ -0,0 +1,235 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.protobuf.ByteString; +import com.google.protobuf.NullValue; +import com.google.protobuf.Timestamp; +import java.util.List; +import lombok.EqualsAndHashCode; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +/** + * TagAndValue represents a value of column in the response + */ +@EqualsAndHashCode(callSuper = true) +public abstract class TagAndValue extends Value { + protected final String tagName; + + protected TagAndValue(String tagName, T value) { + super(value); + this.tagName = tagName; + } + + /** + * @return tag name + */ + public String getTagName() { + return this.tagName; + } + + /** + * @return true if value is null; + */ + public boolean isNull() { + return this.value == null; + } + + /** + * TagValue is referenced from various derived data structs. + * + * @return TagValue to be included + */ + protected abstract BanyandbModel.TagValue buildTypedTagValue(); + + public BanyandbModel.Tag build() { + return BanyandbModel.Tag.newBuilder() + .setKey(this.tagName) + .setValue(buildTypedTagValue()) + .build(); + } + + public static TagAndValue fromProtobuf(BanyandbModel.Tag tag) { + switch (tag.getValue().getValueCase()) { + case INT: + return new LongTagPair(tag.getKey(), tag.getValue().getInt().getValue()); + case STR: + return new StringTagPair(tag.getKey(), tag.getValue().getStr().getValue()); + case INT_ARRAY: + return new LongArrayTagPair(tag.getKey(), tag.getValue().getIntArray().getValueList()); + case STR_ARRAY: + return new StringArrayTagPair(tag.getKey(), tag.getValue().getStrArray().getValueList()); + case BINARY_DATA: + return new BinaryTagPair(tag.getKey(), tag.getValue().getBinaryData()); + case TIMESTAMP: + return new TimestampTagPair(tag.getKey(), tag.getValue().getTimestamp()); + case NULL: + return new NullTagPair(tag.getKey()); + default: + throw new IllegalArgumentException("Unrecognized NullType"); + } + } + + @EqualsAndHashCode(callSuper = true) + public static class StringTagPair extends TagAndValue { + StringTagPair(final String tagName, final String value) { + super(tagName, value); + } + + @Override + protected BanyandbModel.TagValue buildTypedTagValue() { + return BanyandbModel.TagValue.newBuilder() + .setStr(BanyandbModel.Str + .newBuilder() + .setValue(value).build()) + .build(); + } + } + + public static TagAndValue newStringTag(final String tagName, final String value) { + return new StringTagPair(tagName, value); + } + + @EqualsAndHashCode(callSuper = true) + public static class StringArrayTagPair extends TagAndValue> { + StringArrayTagPair(final String tagName, final List value) { + super(tagName, value); + } + + @Override + protected BanyandbModel.TagValue buildTypedTagValue() { + return BanyandbModel.TagValue.newBuilder() + .setStrArray(BanyandbModel.StrArray + .newBuilder() + .addAllValue(value).build()) + .build(); + } + } + + public static TagAndValue> newStringArrayTagPair(final String tagName, final List value) { + return new StringArrayTagPair(tagName, value); + } + + @EqualsAndHashCode(callSuper = true) + public static class LongTagPair extends TagAndValue { + LongTagPair(final String tagName, final Long value) { + super(tagName, value); + } + + @Override + protected BanyandbModel.TagValue buildTypedTagValue() { + return BanyandbModel.TagValue.newBuilder() + .setInt(BanyandbModel.Int + .newBuilder() + .setValue(value).build()) + .build(); + } + } + + public static TagAndValue newLongTag(final String tagName, final long value) { + return new LongTagPair(tagName, value); + } + + @EqualsAndHashCode(callSuper = true) + public static class LongArrayTagPair extends TagAndValue> { + LongArrayTagPair(final String tagName, final List value) { + super(tagName, value); + } + + @Override + protected BanyandbModel.TagValue buildTypedTagValue() { + return BanyandbModel.TagValue.newBuilder() + .setIntArray(BanyandbModel.IntArray + .newBuilder() + .addAllValue(value).build()) + .build(); + } + } + + public static TagAndValue newLongArrayTag(final String tagName, final long value) { + return new LongTagPair(tagName, value); + } + + @EqualsAndHashCode(callSuper = true) + public static class BinaryTagPair extends TagAndValue { + public BinaryTagPair(String fieldName, ByteString byteString) { + super(fieldName, byteString); + } + + @Override + protected BanyandbModel.TagValue buildTypedTagValue() { + return BanyandbModel.TagValue.newBuilder() + .setBinaryData(this.value) + .build(); + } + } + + public static TagAndValue newBinaryTag(final String tagName, final byte[] bytes) { + return new BinaryTagPair(tagName, ByteString.copyFrom(bytes)); + } + + @EqualsAndHashCode(callSuper = true) + public static class TimestampTagPair extends TagAndValue { + TimestampTagPair(final String tagName, final long epochMilli) { + super(tagName, epochMilli); + } + + TimestampTagPair(final String tagName, final Timestamp value) { + super(tagName, value.getSeconds() * 1000 + value.getNanos() / 1000000); + } + + @Override + protected BanyandbModel.TagValue buildTypedTagValue() { + Timestamp timestamp = Timestamp.newBuilder() + .setSeconds(value / 1000) + .setNanos((int) ((value % 1000) * 1000000)) + .build(); + return BanyandbModel.TagValue.newBuilder() + .setTimestamp(timestamp) + .build(); + } + } + + public static TagAndValue newTimestampTag(final String tagName, final long epochMilli) { + return new TimestampTagPair(tagName, epochMilli); + } + + @EqualsAndHashCode(callSuper = true) + public static class NullTagPair extends TagAndValue { + NullTagPair(final String tagName) { + super(tagName, null); + } + + @Override + protected BanyandbModel.TagValue buildTypedTagValue() { + return BanyandbModel.TagValue.newBuilder() + .setNull(NullValue.NULL_VALUE) + .build(); + } + + @Override + public boolean isNull() { + return true; + } + } + + public static TagAndValue newNullTag(final String tagName) { + return new NullTagPair(tagName); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TimestampRange.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TimestampRange.java new file mode 100644 index 000000000000..1bfc9012dafe --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TimestampRange.java @@ -0,0 +1,59 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.protobuf.Timestamp; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.util.TimeUtils; + +@RequiredArgsConstructor +@Getter +@ToString +public class TimestampRange { + static final BanyandbModel.TimeRange MAX_RANGE = BanyandbModel.TimeRange.newBuilder() + .setBegin(TimeUtils.fromEpochNanos(Long.MIN_VALUE)) + .setEnd(TimeUtils.fromEpochNanos(Long.MAX_VALUE)) + .build(); + /** + * start timestamp in timeunit of milliseconds. inclusive. + */ + private final long begin; + + /** + * end timestamp in timeunit of milliseconds. inclusive. + */ + private final long end; + + /** + * @return TimeRange accordingly. + */ + BanyandbModel.TimeRange build() { + final BanyandbModel.TimeRange.Builder builder = BanyandbModel.TimeRange.newBuilder(); + builder.setBegin(Timestamp.newBuilder() + .setSeconds(begin / 1000) + .setNanos((int) (begin % 1000 * 1_000_000))); + builder.setEnd(Timestamp.newBuilder() + .setSeconds(end / 1000) + .setNanos((int) (end % 1000 * 1_000_000))); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TopNQuery.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TopNQuery.java new file mode 100644 index 000000000000..7bb4a386cea8 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TopNQuery.java @@ -0,0 +1,79 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.base.Preconditions; +import java.util.List; +import lombok.Setter; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +@Setter +public class TopNQuery { + private final List groups; + private final String name; + private final TimestampRange timestampRange; + private final int number; + private final AbstractQuery.Sort sort; + private MeasureQuery.Aggregation.Type aggregationType = MeasureQuery.Aggregation.Type.UNSPECIFIED; + private List stages; + /** + * Query conditions. + */ + private List> conditions; + + public TopNQuery(List groups, String name, TimestampRange timestampRange, int number, AbstractQuery.Sort sort) { + Preconditions.checkArgument(sort != AbstractQuery.Sort.UNSPECIFIED); + Preconditions.checkArgument(number > 0); + this.groups = groups; + this.name = name; + this.timestampRange = timestampRange; + this.number = number; + this.sort = sort; + } + + BanyandbMeasure.TopNRequest build() throws BanyanDBException { + BanyandbMeasure.TopNRequest.Builder bld = BanyandbMeasure.TopNRequest.newBuilder() + .setName(name) + .addAllGroups(groups) + .setTimeRange(timestampRange.build()) + .setTopN(number) + .setFieldValueSort(AbstractQuery.Sort.DESC == sort ? BanyandbModel.Sort.SORT_DESC : BanyandbModel.Sort.SORT_ASC); + if (aggregationType == null) { + bld.setAgg(BanyandbModel.AggregationFunction.AGGREGATION_FUNCTION_UNSPECIFIED); + } else { + bld.setAgg(aggregationType.function); + } + if (conditions != null && !conditions.isEmpty()) { + for (final PairQueryCondition expr : conditions) { + if (expr.op != BanyandbModel.Condition.BinaryOp.BINARY_OP_EQ) { + throw new UnsupportedOperationException("only equality is supported"); + } + bld.addConditions(expr.build().getCondition()); + } + } + if (stages != null && !stages.isEmpty()) { + for (String stage : stages) { + bld.addStages(stage); + } + } + return bld.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TopNQueryResponse.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TopNQueryResponse.java new file mode 100644 index 000000000000..a7d5bc544227 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TopNQueryResponse.java @@ -0,0 +1,79 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.protobuf.Timestamp; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +public class TopNQueryResponse { + @Getter + private final List topNLists; + + TopNQueryResponse(BanyandbMeasure.TopNResponse response) { + final List timelines = response.getListsList(); + topNLists = new ArrayList<>(timelines.size()); + for (final BanyandbMeasure.TopNList topNList : timelines) { + topNLists.add(new TopNList(topNList.getTimestamp(), topNList.getItemsList())); + } + } + + public int size() { + return this.topNLists == null ? 0 : this.topNLists.size(); + } + + @Getter + public static class TopNList { + /** + * timestamp of the entity in the timeunit of milliseconds. + */ + private final long timestamp; + private final List items; + + private TopNList(Timestamp ts, List itemsList) { + this.timestamp = ts.getSeconds() * 1000 + ts.getNanos() / 1_000_000; + this.items = new ArrayList<>(itemsList.size()); + for (final BanyandbMeasure.TopNList.Item item : itemsList) { + this.items.add(Item.parseFrom(item)); + } + } + } + + @RequiredArgsConstructor + @Getter + public static class Item { + private final Map> tagValuesMap; + private final Object value; + + static Item parseFrom(BanyandbMeasure.TopNList.Item item) { + final Object fieldValue = DataPoint.convertFileValueToJavaType(item.getValue()); + final Map> map = new HashMap<>(item.getEntityCount()); + for (final BanyandbModel.Tag tag : item.getEntityList()) { + map.put(tag.getKey(), TagAndValue.fromProtobuf(tag)); + } + return new Item(map, fieldValue); + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Trace.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Trace.java new file mode 100644 index 000000000000..efedee8c3cb4 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Trace.java @@ -0,0 +1,46 @@ +/* + * 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.library.banyandb.v1.client; + +import java.util.List; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; + +/** + * Trace represents the trace of a request. + */ +@Getter +@Setter(value = AccessLevel.PRIVATE) +public class Trace { + private String traceId; + private List spans; + private boolean error; + + static Trace convertFromProto(org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Trace protoTrace) { + Trace traceBean = new Trace(); + traceBean.setTraceId(protoTrace.getTraceId()); + traceBean.setError(protoTrace.getError()); + traceBean.setSpans(protoTrace.getSpansList().stream() + .map(Span::convertSpanFromProto) + .collect(Collectors.toList())); + return traceBean; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceQuery.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceQuery.java new file mode 100644 index 000000000000..5e6cadc12ea4 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceQuery.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.library.banyandb.v1.client; + +import java.util.List; +import java.util.Set; +import lombok.Setter; +import org.apache.skywalking.banyandb.trace.v1.BanyandbTrace; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +/** + * TraceQuery is the high-level query API for the trace model. + */ +@Setter +public class TraceQuery extends AbstractQuery { + /** + * The starting row id of the query. Default value is 0. + */ + private int offset; + /** + * The limit size of the query. Default value is 20. + */ + private int limit; + /** + * One order condition is supported and optional. + */ + private OrderBy orderBy; + + /** + * The stages of the trace query. + */ + private Set stages; + + public TraceQuery(final List groups, final String name, final TimestampRange timestampRange, final Set projections) { + super(groups, name, timestampRange, projections); + this.offset = 0; + this.limit = 20; + } + + public TraceQuery(final List groups, final String name, final Set projections) { + this(groups, name, null, projections); + } + + @Override + public TraceQuery and(PairQueryCondition condition) { + return (TraceQuery) super.and(condition); + } + + @Override + public TraceQuery or(PairQueryCondition condition) { + return (TraceQuery) super.or(condition); + } + + public TraceQuery stages(Set stages) { + this.stages = stages; + return this; + } + + @Override + BanyandbTrace.QueryRequest build() throws BanyanDBException { + final BanyandbTrace.QueryRequest.Builder builder = BanyandbTrace.QueryRequest.newBuilder(); + builder.setName(this.name); + builder.addAllGroups(this.groups); + if (timestampRange != null) { + builder.setTimeRange(timestampRange.build()); + } + builder.addAllTagProjection(tagProjections.keySet()); + buildCriteria().ifPresent(builder::setCriteria); + builder.setOffset(offset); + builder.setLimit(limit); + if (orderBy != null) { + builder.setOrderBy(orderBy.build()); + } + if (stages != null && !stages.isEmpty()) { + builder.addAllStages(stages); + } + builder.setTrace(this.trace); + return builder.build(); + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceQueryResponse.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceQueryResponse.java new file mode 100644 index 000000000000..b18e9a4a3e48 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceQueryResponse.java @@ -0,0 +1,69 @@ +/* + * 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.library.banyandb.v1.client; + +import java.util.List; +import org.apache.skywalking.banyandb.trace.v1.BanyandbTrace; + +/** + * TraceQueryResponse is a high-level response object for the trace query API. + */ +public class TraceQueryResponse { + private final BanyandbTrace.QueryResponse response; + private final Trace trace; + + TraceQueryResponse(BanyandbTrace.QueryResponse response) { + this.response = response; + this.trace = Trace.convertFromProto(response.getTraceQueryResult()); + } + + /** + * Get the list of traces returned by the query. + * + * @return list of traces, each containing spans grouped by trace ID + */ + public List getTraces() { + return response.getTracesList(); + } + + /** + * Get the trace query execution trace if enabled. + */ + public Trace getTraceResult() { + return this.trace; + } + + /** + * Get the total number of traces returned. + * + * @return trace count + */ + public int size() { + return response.getTracesCount(); + } + + /** + * Check if the response is empty. + * + * @return true if no traces were returned + */ + public boolean isEmpty() { + return size() == 0; + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceWrite.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceWrite.java new file mode 100644 index 000000000000..45c0bc31a862 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/TraceWrite.java @@ -0,0 +1,153 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import lombok.Getter; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.banyandb.trace.v1.BanyandbTrace; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Serializable; + +/** + * TraceWrite represents a write operation, including necessary fields. + */ +public class TraceWrite extends AbstractWrite { + /** + * Span data in binary format + */ + @Getter + private ByteString span; + + /** + * Version for write request + */ + @Getter + private long version; + + private final Map/*tagValue*/> tags; + + /** + * Create a TraceWrite without initial timestamp. + */ + TraceWrite(BanyandbCommon.Metadata entityMetadata) { + super(entityMetadata); + this.span = ByteString.EMPTY; + this.version = 1L; + this.tags = new TreeMap<>(); + } + + public TraceWrite tag(String tagName, Serializable tagValue) throws BanyanDBException { + this.tags.put(tagName, tagValue); + return this; + } + + /** + * Set span data + * + * @param span span data in bytes + */ + public TraceWrite span(byte[] span) { + this.span = ByteString.copyFrom(span); + return this; + } + + /** + * Set span data + * + * @param span span data as ByteString + */ + public TraceWrite span(ByteString span) { + this.span = span; + return this; + } + + /** + * Set version + * + * @param version write request version + */ + public TraceWrite version(long version) { + this.version = version; + return this; + } + + /** + * Build a write request + * + * @return {@link BanyandbTrace.WriteRequest} for the bulk process. + */ + @Override + protected BanyandbTrace.WriteRequest build(BanyandbCommon.Metadata metadata) { + final BanyandbTrace.WriteRequest.Builder builder = BanyandbTrace.WriteRequest.newBuilder(); + builder.setMetadata(metadata); + BanyandbTrace.TagSpec.Builder tagSpecBuilder = BanyandbTrace.TagSpec.newBuilder(); + + List tagValues = new ArrayList<>(); + for (Map.Entry> tagEntry : this.tags.entrySet()) { + tagSpecBuilder.addTagNames(tagEntry.getKey()); + tagValues.add(tagEntry.getValue().serialize()); + } + + builder.setTagSpec(tagSpecBuilder); + builder.addAllTags(tagValues); + builder.setSpan(this.span); + builder.setVersion(this.version); + return builder.build(); + } + + /** + * Build a write request without metadata and tag specs. + * + * @return {@link BanyandbTrace.WriteRequest} for the bulk process. + */ + @Override + protected BanyandbTrace.WriteRequest buildValues() { + final BanyandbTrace.WriteRequest.Builder builder = BanyandbTrace.WriteRequest.newBuilder(); + + List tagValues = new ArrayList<>(); + for (Map.Entry> tagEntry : this.tags.entrySet()) { + tagValues.add(tagEntry.getValue().serialize()); + } + + builder.addAllTags(tagValues); + builder.setSpan(this.span); + builder.setVersion(this.version); + return builder.build(); + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("group=").append(entityMetadata.getGroup()).append(", ").append("name=") + .append(entityMetadata.getName()).append(", ").append("timestamp=").append(timestamp).append(", "); + for (Map.Entry> tagEntry : tags.entrySet()) { + String tagName = tagEntry.getKey(); + Serializable tagValue = tagEntry.getValue(); + stringBuilder.append(tagName).append("=") + .append(tagValue.serialize()).append(", "); + } + return stringBuilder.toString(); + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Value.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Value.java new file mode 100644 index 000000000000..667f71692568 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/Value.java @@ -0,0 +1,338 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.base.Strings; +import com.google.protobuf.ByteString; +import com.google.protobuf.Timestamp; +import java.util.List; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Serializable; + +import static com.google.protobuf.NullValue.NULL_VALUE; + +/** + * Field represents a value in the write-op or response. + */ +@EqualsAndHashCode +public abstract class Value { + @Getter + protected final T value; + + protected Value(T value) { + this.value = value; + } + + /** + * NullTagValue is a value which can be converted to {@link com.google.protobuf.NullValue}. + * Users should use the singleton instead of create a new instance everytime. + */ + public static class NullTagValue extends Value implements Serializable { + private static final NullTagValue INSTANCE = new NullTagValue(); + + private NullTagValue() { + super(null); + } + + @Override + public BanyandbModel.TagValue serialize() { + return BanyandbModel.TagValue.newBuilder().setNull(NULL_VALUE).build(); + } + } + + /** + * The value of a String type tag. + */ + public static class StringTagValue extends Value implements Serializable { + private StringTagValue(String value) { + super(value); + } + + @Override + public BanyandbModel.TagValue serialize() { + return BanyandbModel.TagValue.newBuilder().setStr(BanyandbModel.Str.newBuilder().setValue(value)).build(); + } + } + + /** + * The value of a String array type tag. + */ + public static class StringArrayTagValue extends Value> implements Serializable { + private StringArrayTagValue(List value) { + super(value); + } + + @Override + public BanyandbModel.TagValue serialize() { + return BanyandbModel.TagValue.newBuilder().setStrArray(BanyandbModel.StrArray.newBuilder().addAllValue(value)).build(); + } + } + + /** + * The value of an int64(Long) type tag. + */ + public static class LongTagValue extends Value implements Serializable { + private LongTagValue(Long value) { + super(value); + } + + @Override + public BanyandbModel.TagValue serialize() { + return BanyandbModel.TagValue.newBuilder().setInt(BanyandbModel.Int.newBuilder().setValue(value)).build(); + } + } + + /** + * The value of an int64(Long) array type tag. + */ + public static class LongArrayTagValue extends Value> implements Serializable { + private LongArrayTagValue(List value) { + super(value); + } + + @Override + public BanyandbModel.TagValue serialize() { + return BanyandbModel.TagValue.newBuilder().setIntArray(BanyandbModel.IntArray.newBuilder().addAllValue(value)).build(); + } + } + + /** + * The value of a byte array(ByteString) type tag. + */ + public static class BinaryTagValue extends Value implements Serializable { + public BinaryTagValue(ByteString byteString) { + super(byteString); + } + + @Override + public BanyandbModel.TagValue serialize() { + return BanyandbModel.TagValue.newBuilder().setBinaryData(value).build(); + } + } + + /** + * The value of a timestamp type tag. + */ + public static class TimestampTagValue extends Value implements Serializable { + private TimestampTagValue(Long value) { + super(value); + } + + @Override + public BanyandbModel.TagValue serialize() { + Timestamp timestamp = toProtobufTimestamp(value); + return BanyandbModel.TagValue.newBuilder().setTimestamp(timestamp).build(); + } + } + + /** + * Utility method to convert milliseconds to protobuf Timestamp. + */ + private static Timestamp toProtobufTimestamp(long millis) { + return Timestamp.newBuilder() + .setSeconds(millis / 1000) + .setNanos((int) ((millis % 1000) * 1000000)) + .build(); + } + + /** + * Construct a string tag + * + * @param val payload + * @return Anonymous tag with String payload + */ + public static Serializable stringTagValue(String val) { + if (val == null) { + return nullTagValue(); + } + return new StringTagValue(val); + } + + /** + * Construct a numeric tag + * + * @param val payload + * @return Anonymous tag with numeric payload + */ + public static Serializable longTagValue(Long val) { + if (val == null) { + return nullTagValue(); + } + return new LongTagValue(val); + } + + /** + * Construct a string array tag + * + * @param val payload + * @return Anonymous tag with string array payload + */ + public static Serializable stringArrayTagValue(List val) { + if (val == null) { + return nullTagValue(); + } + return new StringArrayTagValue(val); + } + + /** + * Construct a byte array tag. + * + * @param bytes binary data + * @return Anonymous tag with binary payload + */ + public static Serializable binaryTagValue(byte[] bytes) { + if (bytes == null) { + return nullTagValue(); + } + return new BinaryTagValue(ByteString.copyFrom(bytes)); + } + + /** + * Construct a long array tag + * + * @param val payload + * @return Anonymous tag with numeric array payload + */ + public static Serializable longArrayTag(List val) { + if (val == null) { + return nullTagValue(); + } + return new LongArrayTagValue(val); + } + + /** + * Construct a timestamp tag + * + * @param epochMilli payload in milliseconds + * @return Anonymous tag with timestamp payload + */ + public static Serializable timestampTagValue(long epochMilli) { + return new TimestampTagValue(epochMilli); + } + + public static Serializable nullTagValue() { + return NullTagValue.INSTANCE; + } + + /** + * The value of a String type field. + */ + public static class StringFieldValue extends Value implements Serializable { + private StringFieldValue(String value) { + super(value); + } + + @Override + public BanyandbModel.FieldValue serialize() { + return BanyandbModel.FieldValue.newBuilder().setStr(BanyandbModel.Str.newBuilder().setValue(value)).build(); + } + } + + public static Serializable stringFieldValue(String val) { + if (Strings.isNullOrEmpty(val)) { + return nullFieldValue(); + } + return new StringFieldValue(val); + } + + /** + * NullFieldValue is a value which can be converted to {@link com.google.protobuf.NullValue}. + * Users should use the singleton instead of create a new instance everytime. + */ + public static class NullFieldValue extends Value implements Serializable { + private static final NullFieldValue INSTANCE = new NullFieldValue(); + + private NullFieldValue() { + super(null); + } + + @Override + public BanyandbModel.FieldValue serialize() { + return BanyandbModel.FieldValue.newBuilder().setNull(NULL_VALUE).build(); + } + } + + public static Serializable nullFieldValue() { + return NullFieldValue.INSTANCE; + } + + /** + * The value of an int64(Long) type field. + */ + public static class LongFieldValue extends Value implements Serializable { + private LongFieldValue(Long value) { + super(value); + } + + @Override + public BanyandbModel.FieldValue serialize() { + return BanyandbModel.FieldValue.newBuilder().setInt(BanyandbModel.Int.newBuilder().setValue(value)).build(); + } + } + + /** + * The value of a float type field. + */ + public static class FloatFieldValue extends Value implements Serializable { + private FloatFieldValue(Float value) { + super(value); + } + + @Override + public BanyandbModel.FieldValue serialize() { + return BanyandbModel.FieldValue.newBuilder().setFloat(BanyandbModel.Float.newBuilder().setValue(value)).build(); + } + } + + /** + * Construct a numeric tag + * + * @param val payload + * @return Anonymous tag with numeric payload + */ + public static Serializable longFieldValue(long val) { + return new LongFieldValue(val); + } + + /** + * The value of a byte array(ByteString) type field. + */ + public static class BinaryFieldValue extends Value implements Serializable { + public BinaryFieldValue(ByteString byteString) { + super(byteString); + } + + @Override + public BanyandbModel.FieldValue serialize() { + return BanyandbModel.FieldValue.newBuilder().setBinaryData(value).build(); + } + } + + /** + * Construct a byte array tag. + * + * @param bytes binary data + * @return Anonymous tag with binary payload + */ + public static Serializable binaryFieldValue(byte[] bytes) { + return new BinaryFieldValue(ByteString.copyFrom(bytes)); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/auth/AuthInterceptor.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/auth/AuthInterceptor.java new file mode 100644 index 000000000000..ba3e5cb401a2 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/auth/AuthInterceptor.java @@ -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.library.banyandb.v1.client.auth; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; + +public class AuthInterceptor implements ClientInterceptor { + private final String username; + private final String password; + + private static final Metadata.Key USERNAME_KEY = + Metadata.Key.of("username", Metadata.ASCII_STRING_MARSHALLER); + private static final Metadata.Key PASSWORD_KEY = + Metadata.Key.of("password", Metadata.ASCII_STRING_MARSHALLER); + + public AuthInterceptor(String username, String password) { + this.username = username; + this.password = password; + } + + @Override + public ClientCall interceptCall( + MethodDescriptor method, + CallOptions callOptions, + Channel next) { + + return new ForwardingClientCall.SimpleForwardingClientCall( + next.newCall(method, callOptions)) { + @Override + public void start(Listener responseListener, Metadata headers) { + headers.put(USERNAME_KEY, username); + headers.put(PASSWORD_KEY, password); + + super.start(responseListener, headers); + } + }; + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/HandleExceptionsWith.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/HandleExceptionsWith.java new file mode 100644 index 000000000000..5cddfcf51abd --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/HandleExceptionsWith.java @@ -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.library.banyandb.v1.client.grpc; + +import com.google.common.collect.Sets; +import io.grpc.Status; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBGrpcApiExceptionFactory; + +public class HandleExceptionsWith { + private HandleExceptionsWith() { + } + + private static final BanyanDBGrpcApiExceptionFactory EXCEPTION_FACTORY = new BanyanDBGrpcApiExceptionFactory( + // Exceptions caused by network issues are retryable + Sets.newHashSet(Status.Code.UNAVAILABLE, Status.Code.DEADLINE_EXCEEDED) + ); + + /** + * call the underlying operation and get response from the future. + * + * @param respSupplier a supplier which returns response + * @param a generic type of user-defined gRPC response + * @return response in the type of defined in the gRPC protocol + * @throws BanyanDBException if the execution of the future itself thrown an exception + */ + public static RESP callAndTranslateApiException(SupplierWithIO respSupplier) throws BanyanDBException { + try { + return respSupplier.get(); + } catch (Exception exception) { + throw EXCEPTION_FACTORY.createException(exception); + } + } + + @FunctionalInterface + public interface SupplierWithIO { + T get() throws E; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/MetadataClient.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/MetadataClient.java new file mode 100644 index 000000000000..f7e2529ba698 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/MetadataClient.java @@ -0,0 +1,99 @@ +/* + * 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.library.banyandb.v1.client.grpc; + +import com.google.protobuf.GeneratedMessageV3; +import io.grpc.stub.AbstractBlockingStub; +import java.util.List; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.ResourceExist; + +/** + * abstract metadata client which defines CRUD operations for a specific kind of schema. + * + * @param

ProtoBuf: schema defined in ProtoBuf format + */ +public abstract class MetadataClient, P extends GeneratedMessageV3> { + public static final long DEFAULT_MOD_REVISION = 0; + + protected final STUB stub; + + protected MetadataClient(STUB stub) { + this.stub = stub; + } + + /** + * Create a schema + * + * @param payload the schema to be created + * @return the mod revision of the schema + * @throws BanyanDBException a wrapped exception to the underlying gRPC calls + */ + public abstract long create(P payload) throws BanyanDBException; + + /** + * Update the schema + * + * @param payload the schema which will be updated with the given name and group + * @throws BanyanDBException a wrapped exception to the underlying gRPC calls + */ + public abstract void update(P payload) throws BanyanDBException; + + /** + * Delete a schema + * + * @param group the group of the schema to be removed + * @param name the name of the schema to be removed + * @return whether this schema is deleted + * @throws BanyanDBException a wrapped exception to the underlying gRPC calls + */ + public abstract boolean delete(String group, String name) throws BanyanDBException; + + /** + * Get a schema with name + * + * @param group the group of the schema to be found + * @param name the name of the schema to be found + * @return the schema, null if not found + * @throws BanyanDBException a wrapped exception to the underlying gRPC calls + */ + public abstract P get(String group, String name) throws BanyanDBException; + + /** + * Check whether a schema exists + * + * @param group the group of the schema to be found + * @param name the name of the schema to be found + * @return whether resource exists + * @throws BanyanDBException a wrapped exception to the underlying gRPC calls + */ + public abstract ResourceExist exist(String group, String name) throws BanyanDBException; + + /** + * List all schemas with the same group name + * + * @return a list of schemas found + * @throws BanyanDBException a wrapped exception to the underlying gRPC calls + */ + public abstract List

list(String group) throws BanyanDBException; + + protected RESP execute(HandleExceptionsWith.SupplierWithIO supplier) throws BanyanDBException { + return HandleExceptionsWith.callAndTranslateApiException(supplier); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelFactory.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelFactory.java new file mode 100644 index 000000000000..2a1e5452f51b --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelFactory.java @@ -0,0 +1,26 @@ +/* + * 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.library.banyandb.v1.client.grpc.channel; + +import io.grpc.ManagedChannel; +import java.io.IOException; + +public interface ChannelFactory { + ManagedChannel create() throws IOException; +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManager.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManager.java new file mode 100644 index 000000000000..89a8d7568561 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManager.java @@ -0,0 +1,220 @@ +/* + * 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.library.banyandb.v1.client.grpc.channel; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableSet; +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ConnectivityState; +import io.grpc.ForwardingClientCall; +import io.grpc.ForwardingClientCallListener; +import io.grpc.ManagedChannel; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.Status; +import java.io.IOException; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class ChannelManager extends ManagedChannel { + private final LazyReferenceChannel lazyChannel = new LazyReferenceChannel(); + + private static final Set SC_NETWORK = ImmutableSet.of( + Status.Code.UNAVAILABLE, Status.Code.PERMISSION_DENIED, + Status.Code.UNAUTHENTICATED, Status.Code.RESOURCE_EXHAUSTED, Status.Code.UNKNOWN + ); + + private final ChannelManagerSettings settings; + private final ChannelFactory channelFactory; + private final ScheduledExecutorService executor; + @VisibleForTesting + final AtomicReference entryRef = new AtomicReference<>(); + + public static ChannelManager create(ChannelManagerSettings settings, ChannelFactory channelFactory) + throws IOException { + return new ChannelManager(settings, channelFactory, Executors.newSingleThreadScheduledExecutor()); + } + + ChannelManager(ChannelManagerSettings settings, ChannelFactory channelFactory, ScheduledExecutorService executor) throws IOException { + this.settings = settings; + this.channelFactory = channelFactory; + this.executor = executor; + + entryRef.set(new Entry(channelFactory.create())); + + this.executor.scheduleAtFixedRate( + this::refreshSafely, + settings.getRefreshInterval(), + settings.getRefreshInterval(), + TimeUnit.SECONDS + ); + } + + private void refreshSafely() { + try { + refresh(); + } catch (Exception e) { + log.warn("Failed to refresh channels", e); + } + } + + void refresh() throws IOException { + Entry entry = entryRef.get(); + if (!entry.needReconnect) { + return; + } + if (entry.isConnected(entry.reconnectCount.incrementAndGet() > this.settings.getForceReconnectionThreshold())) { + // Reconnect to the same server is automatically done by GRPC + // clear the flags + entry.reset(); + return; + } + Entry replacedEntry = entryRef.getAndSet(new Entry(this.channelFactory.create())); + replacedEntry.shutdown(); + } + + @Override + public ManagedChannel shutdown() { + entryRef.get().channel.shutdown(); + if (executor != null) { + // shutdownNow will cancel scheduled tasks + executor.shutdownNow(); + } + return this; + } + + @Override + public boolean isShutdown() { + if (!this.entryRef.get().channel.isShutdown()) { + return false; + } + return executor == null || executor.isShutdown(); + } + + @Override + public boolean isTerminated() { + if (!this.entryRef.get().channel.isTerminated()) { + return false; + } + return executor == null || executor.isTerminated(); + } + + @Override + public ManagedChannel shutdownNow() { + entryRef.get().channel.shutdownNow(); + if (executor != null) { + executor.shutdownNow(); + } + return this; + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { + long endTimeNanos = System.nanoTime() + unit.toNanos(timeout); + entryRef.get().channel.awaitTermination(endTimeNanos - System.nanoTime(), TimeUnit.NANOSECONDS); + if (executor != null) { + long awaitTimeNanos = endTimeNanos - System.nanoTime(); + executor.awaitTermination(awaitTimeNanos, TimeUnit.NANOSECONDS); + } + return isTerminated(); + } + + @Override + public ClientCall newCall(MethodDescriptor methodDescriptor, CallOptions callOptions) { + return lazyChannel.newCall(methodDescriptor, callOptions); + } + + @Override + public String authority() { + return this.entryRef.get().channel.authority(); + } + + @RequiredArgsConstructor + static class Entry { + final ManagedChannel channel; + + final AtomicInteger reconnectCount = new AtomicInteger(0); + + volatile boolean needReconnect = false; + + boolean isConnected(boolean requestConnection) { + return this.channel.getState(requestConnection) == ConnectivityState.READY; + } + + void shutdown() { + this.channel.shutdown(); + } + + void reset() { + needReconnect = false; + reconnectCount.set(0); + } + } + + private class LazyReferenceChannel extends Channel { + @Override + public ClientCall newCall(MethodDescriptor methodDescriptor, CallOptions callOptions) { + Entry entry = entryRef.get(); + + return new NetworkExceptionAwareClientCall<>(entry.channel.newCall(methodDescriptor, callOptions), entry); + } + + @Override + public String authority() { + return ChannelManager.this.authority(); + } + } + + static class NetworkExceptionAwareClientCall extends ForwardingClientCall.SimpleForwardingClientCall { + final Entry entry; + + public NetworkExceptionAwareClientCall(ClientCall delegate, Entry entry) { + super(delegate); + this.entry = entry; + } + + @Override + public void start(Listener responseListener, Metadata headers) { + super.start( + new ForwardingClientCallListener.SimpleForwardingClientCallListener(responseListener) { + @Override + public void onClose(Status status, Metadata trailers) { + if (isNetworkError(status)) { + entry.needReconnect = true; + } + super.onClose(status, trailers); + } + }, + headers); + } + } + + static boolean isNetworkError(Status status) { + return SC_NETWORK.contains(status.getCode()); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManagerSettings.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManagerSettings.java new file mode 100644 index 000000000000..043c3c0a8341 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManagerSettings.java @@ -0,0 +1,30 @@ +/* + * 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.library.banyandb.v1.client.grpc.channel; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class ChannelManagerSettings { + private final long refreshInterval; + private final long forceReconnectionThreshold; +} + diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/DefaultChannelFactory.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/DefaultChannelFactory.java new file mode 100644 index 000000000000..089868c9dd12 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/DefaultChannelFactory.java @@ -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.library.banyandb.v1.client.grpc.channel; + +import io.grpc.ManagedChannel; +import io.grpc.netty.GrpcSslContexts; +import io.grpc.netty.NegotiationType; +import io.grpc.netty.NettyChannelBuilder; +import io.netty.handler.ssl.SslContextBuilder; +import io.netty.util.internal.PlatformDependent; +import java.io.File; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.URI; +import java.net.UnknownHostException; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.skywalking.library.banyandb.v1.client.Options; + +@Slf4j +@RequiredArgsConstructor +public class DefaultChannelFactory implements ChannelFactory { + private final URI[] targets; + private final Options options; + + @Override + public ManagedChannel create() throws IOException { + NettyChannelBuilder managedChannelBuilder = NettyChannelBuilder.forAddress(resolveAddress()) + .maxInboundMessageSize(options.getMaxInboundMessageSize()) + .usePlaintext(); + + File caFile = new File(options.getSslTrustCAPath()); + boolean isCAFileExist = caFile.exists() && caFile.isFile(); + if (options.isForceTLS() || isCAFileExist) { + SslContextBuilder builder = GrpcSslContexts.forClient(); + + if (isCAFileExist) { + builder.trustManager(caFile); + } + managedChannelBuilder.negotiationType(NegotiationType.TLS).sslContext(builder.build()); + } + return managedChannelBuilder.build(); + } + + private SocketAddress resolveAddress() throws UnknownHostException { + int numAddresses = this.targets.length; + if (numAddresses < 1) { + throw new UnknownHostException(); + } + int offset = numAddresses == 1 ? 0 : PlatformDependent.threadLocalRandom().nextInt(numAddresses); + return new InetSocketAddress(this.targets[offset].getHost(), this.targets[offset].getPort()); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/AbortedException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/AbortedException.java new file mode 100644 index 000000000000..a7b64e162b26 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/AbortedException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class AbortedException extends BanyanDBException { + public AbortedException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public AbortedException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/AlreadyExistsException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/AlreadyExistsException.java new file mode 100644 index 000000000000..2d9c08ddf2bd --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/AlreadyExistsException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class AlreadyExistsException extends BanyanDBException { + public AlreadyExistsException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public AlreadyExistsException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBApiExceptionFactory.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBApiExceptionFactory.java new file mode 100644 index 000000000000..9cea391b7d45 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBApiExceptionFactory.java @@ -0,0 +1,64 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +class BanyanDBApiExceptionFactory { + private BanyanDBApiExceptionFactory() { + } + + public static BanyanDBException createException(Throwable cause, Status.Code statusCode, boolean retryable) { + switch (statusCode) { + case CANCELLED: + return new CancelledException(cause, statusCode, retryable); + case NOT_FOUND: + return new NotFoundException(cause, statusCode, retryable); + case INVALID_ARGUMENT: + return new InvalidArgumentException(cause, statusCode, retryable); + case DEADLINE_EXCEEDED: + return new DeadlineExceededException(cause, statusCode, retryable); + case ALREADY_EXISTS: + return new AlreadyExistsException(cause, statusCode, retryable); + case PERMISSION_DENIED: + return new PermissionDeniedException(cause, statusCode, retryable); + case RESOURCE_EXHAUSTED: + return new ResourceExhaustedException(cause, statusCode, retryable); + case FAILED_PRECONDITION: + return new FailedPreconditionException(cause, statusCode, retryable); + case ABORTED: + return new AbortedException(cause, statusCode, retryable); + case OUT_OF_RANGE: + return new OutOfRangeException(cause, statusCode, retryable); + case UNIMPLEMENTED: + return new UnimplementedException(cause, statusCode, retryable); + case INTERNAL: + return new InternalException(cause, statusCode, retryable); + case UNAVAILABLE: + return new UnavailableException(cause, statusCode, retryable); + case DATA_LOSS: + return new DataLossException(cause, statusCode, retryable); + case UNAUTHENTICATED: + return new UnauthenticatedException(cause, statusCode, retryable); + case UNKNOWN: // Fall through. + default: + return new UnknownException(cause, statusCode, retryable); + } + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBException.java new file mode 100644 index 000000000000..2371cdc5827f --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBException.java @@ -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.library.banyandb.v1.client.grpc.exception; + +import com.google.common.base.Preconditions; +import io.grpc.Status; +import lombok.Getter; + +/** + * BanyanDBException represents an exception thrown during a gRPC call. + */ +@Getter +public class BanyanDBException extends Exception { + private final Status.Code status; + private final boolean retryable; + + public BanyanDBException(Throwable cause, Status.Code status, boolean retryable) { + super(cause); + this.status = Preconditions.checkNotNull(status); + this.retryable = retryable; + } + + public BanyanDBException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause); + this.status = Preconditions.checkNotNull(status); + this.retryable = retryable; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBGrpcApiExceptionFactory.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBGrpcApiExceptionFactory.java new file mode 100644 index 000000000000..d9037408697a --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/BanyanDBGrpcApiExceptionFactory.java @@ -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.library.banyandb.v1.client.grpc.exception; + +import com.google.common.collect.ImmutableSet; +import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.StatusRuntimeException; +import java.util.Set; + +public class BanyanDBGrpcApiExceptionFactory { + private final ImmutableSet retryableCodes; + + public BanyanDBGrpcApiExceptionFactory(Set retryCodes) { + this.retryableCodes = ImmutableSet.copyOf(retryCodes); + } + + public BanyanDBException createException(Throwable throwable) { + if (throwable instanceof StatusException) { + StatusException e = (StatusException) throwable; + return create(throwable, e.getStatus().getCode()); + } else if (throwable instanceof StatusRuntimeException) { + StatusRuntimeException e = (StatusRuntimeException) throwable; + return create(throwable, e.getStatus().getCode()); + } else if (throwable instanceof BanyanDBException) { + return (BanyanDBException) throwable; + } else { + // Do not retry on unknown throwable, even when UNKNOWN is in retryableCodes + return BanyanDBApiExceptionFactory.createException( + throwable, Status.Code.UNKNOWN, false); + } + } + + private BanyanDBException create(Throwable throwable, Status.Code statusCode) { + boolean retryable = retryableCodes.contains(statusCode); + return BanyanDBApiExceptionFactory.createException(throwable, statusCode, retryable); + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/CancelledException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/CancelledException.java new file mode 100644 index 000000000000..82f69003883e --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/CancelledException.java @@ -0,0 +1,32 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class CancelledException extends BanyanDBException { + public CancelledException(Throwable cause, Status.Code statusCode, boolean retryable) { + super(cause, statusCode, retryable); + } + + public CancelledException( + String message, Throwable cause, Status.Code statusCode, boolean retryable) { + super(message, cause, statusCode, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/DataLossException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/DataLossException.java new file mode 100644 index 000000000000..5374683b7435 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/DataLossException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class DataLossException extends BanyanDBException { + public DataLossException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public DataLossException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/DeadlineExceededException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/DeadlineExceededException.java new file mode 100644 index 000000000000..ee9bc086a30e --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/DeadlineExceededException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class DeadlineExceededException extends BanyanDBException { + public DeadlineExceededException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public DeadlineExceededException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/FailedPreconditionException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/FailedPreconditionException.java new file mode 100644 index 000000000000..a95da49ada7b --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/FailedPreconditionException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class FailedPreconditionException extends BanyanDBException { + public FailedPreconditionException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public FailedPreconditionException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InternalException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InternalException.java new file mode 100644 index 000000000000..c1550c4f077c --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InternalException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class InternalException extends BanyanDBException { + public InternalException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public InternalException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InvalidArgumentException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InvalidArgumentException.java new file mode 100644 index 000000000000..f73f610d13f3 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InvalidArgumentException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class InvalidArgumentException extends BanyanDBException { + public InvalidArgumentException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public InvalidArgumentException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InvalidReferenceException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InvalidReferenceException.java new file mode 100644 index 000000000000..668af315ae5e --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/InvalidReferenceException.java @@ -0,0 +1,38 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class InvalidReferenceException extends BanyanDBException { + private final String refName; + + private InvalidReferenceException(String refName, String message) { + super(message, null, Status.Code.INVALID_ARGUMENT, false); + this.refName = refName; + } + + public static InvalidReferenceException fromInvalidTag(String tagName) { + return new InvalidReferenceException(tagName, "invalid ref to tag " + tagName); + } + + public static InvalidReferenceException fromInvalidField(String fieldName) { + return new InvalidReferenceException(fieldName, "invalid ref to field " + fieldName); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/NotFoundException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/NotFoundException.java new file mode 100644 index 000000000000..4efce663970b --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/NotFoundException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class NotFoundException extends BanyanDBException { + public NotFoundException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public NotFoundException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/OutOfRangeException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/OutOfRangeException.java new file mode 100644 index 000000000000..ea6890b1c949 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/OutOfRangeException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class OutOfRangeException extends BanyanDBException { + public OutOfRangeException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public OutOfRangeException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/PermissionDeniedException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/PermissionDeniedException.java new file mode 100644 index 000000000000..4bbc6b14f4e0 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/PermissionDeniedException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class PermissionDeniedException extends BanyanDBException { + public PermissionDeniedException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public PermissionDeniedException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/ResourceExhaustedException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/ResourceExhaustedException.java new file mode 100644 index 000000000000..328b95d3c033 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/ResourceExhaustedException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class ResourceExhaustedException extends BanyanDBException { + public ResourceExhaustedException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public ResourceExhaustedException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnauthenticatedException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnauthenticatedException.java new file mode 100644 index 000000000000..c18ae43f495d --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnauthenticatedException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class UnauthenticatedException extends BanyanDBException { + public UnauthenticatedException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public UnauthenticatedException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnavailableException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnavailableException.java new file mode 100644 index 000000000000..0f3163062325 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnavailableException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class UnavailableException extends BanyanDBException { + public UnavailableException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public UnavailableException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnimplementedException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnimplementedException.java new file mode 100644 index 000000000000..3003c7a62a1e --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnimplementedException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class UnimplementedException extends BanyanDBException { + public UnimplementedException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public UnimplementedException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnknownException.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnknownException.java new file mode 100644 index 000000000000..c41ef58a6eb9 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/grpc/exception/UnknownException.java @@ -0,0 +1,31 @@ +/* + * 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.library.banyandb.v1.client.grpc.exception; + +import io.grpc.Status; + +public class UnknownException extends BanyanDBException { + public UnknownException(Throwable cause, Status.Code status, boolean retryable) { + super(cause, status, retryable); + } + + public UnknownException(String message, Throwable cause, Status.Code status, boolean retryable) { + super(message, cause, status, retryable); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/Duration.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/Duration.java new file mode 100644 index 000000000000..b6e570ca94d7 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/Duration.java @@ -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.library.banyandb.v1.client.metadata; + +import com.google.common.base.Strings; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode +public class Duration { + private static final Pattern DURATION_PATTERN = + Pattern.compile("(((?\\d+)d)?((?\\d+)h)?((?\\d+)m)?|0)"); + private static final long MINUTES_PER_HOUR = 60; + private static final long HOURS_PER_DAY = 24; + private static final long MINUTES_PER_DAY = MINUTES_PER_HOUR * HOURS_PER_DAY; + + @EqualsAndHashCode.Exclude + private volatile String text; + private final long minutes; + + private Duration(long minutes) { + this.minutes = minutes; + } + + public String format() { + if (!Strings.isNullOrEmpty(text)) { + return text; + } + + final StringBuilder builder = new StringBuilder(); + long minutes = this.minutes; + if (minutes >= MINUTES_PER_DAY) { + long weeks = minutes / MINUTES_PER_DAY; + builder.append(weeks).append("d"); + minutes = minutes % MINUTES_PER_DAY; + } + if (minutes >= MINUTES_PER_HOUR) { + long weeks = minutes / MINUTES_PER_HOUR; + builder.append(weeks).append("h"); + minutes = minutes % MINUTES_PER_HOUR; + } + if (minutes > 0) { + builder.append(minutes).append("m"); + } + this.text = builder.toString(); + return this.text; + } + + public Duration add(Duration duration) { + return new Duration(this.minutes + duration.minutes); + } + + public static Duration parse(String text) { + if (Strings.isNullOrEmpty(text)) { + return new Duration(0); + } + Matcher matcher = DURATION_PATTERN.matcher(text); + if (!matcher.find()) { + return new Duration(0); + } + long total = 0; + final String days = matcher.group("day"); + if (!Strings.isNullOrEmpty(days)) { + total += Long.parseLong(days) * MINUTES_PER_DAY; + } + final String hours = matcher.group("hour"); + if (!Strings.isNullOrEmpty(hours)) { + total += Long.parseLong(hours) * MINUTES_PER_HOUR; + } + final String minutes = matcher.group("minute"); + if (!Strings.isNullOrEmpty(minutes)) { + total += Long.parseLong(minutes); + } + return new Duration(total); + } + + public static Duration ofMinutes(long minutes) { + return new Duration(minutes); + } + + public static Duration ofHours(long hours) { + return new Duration(hours * MINUTES_PER_HOUR); + } + + public static Duration ofDays(long days) { + return ofHours(days * HOURS_PER_DAY); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/GroupMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/GroupMetadataRegistry.java new file mode 100644 index 000000000000..66243d020b95 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/GroupMetadataRegistry.java @@ -0,0 +1,87 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Group; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.GroupRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class GroupMetadataRegistry extends MetadataClient { + + public GroupMetadataRegistry(Channel channel) { + super(GroupRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(Group payload) throws BanyanDBException { + execute(() -> stub.create(BanyandbDatabase.GroupRegistryServiceCreateRequest.newBuilder() + .setGroup(payload) + .build())); + return DEFAULT_MOD_REVISION; + } + + @Override + public void update(Group payload) throws BanyanDBException { + execute(() -> stub.update(BanyandbDatabase.GroupRegistryServiceUpdateRequest.newBuilder() + .setGroup(payload) + .build())); + } + + @Override + public boolean delete(String group, String name) throws BanyanDBException { + BanyandbDatabase.GroupRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.GroupRegistryServiceDeleteRequest.newBuilder() + .setGroup(name) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public Group get(String group, String name) throws BanyanDBException { + BanyandbDatabase.GroupRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.GroupRegistryServiceGetRequest.newBuilder() + .setGroup(name) + .build())); + + return resp.getGroup(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.GroupRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.GroupRegistryServiceExistRequest.newBuilder() + .setGroup(name) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasGroup()).build(); + } + + @Override + public List list(String group) throws BanyanDBException { + BanyandbDatabase.GroupRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.GroupRegistryServiceListRequest.newBuilder() + .build())); + + return resp.getGroupList(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/IndexRuleBindingMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/IndexRuleBindingMetadataRegistry.java new file mode 100644 index 000000000000..d5bbffa2ab9a --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/IndexRuleBindingMetadataRegistry.java @@ -0,0 +1,89 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRuleBinding; +import org.apache.skywalking.banyandb.database.v1.IndexRuleBindingRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class IndexRuleBindingMetadataRegistry extends MetadataClient { + + public IndexRuleBindingMetadataRegistry(Channel channel) { + super(IndexRuleBindingRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(IndexRuleBinding payload) throws BanyanDBException { + execute(() -> stub.create(BanyandbDatabase.IndexRuleBindingRegistryServiceCreateRequest.newBuilder() + .setIndexRuleBinding(payload) + .build())); + return DEFAULT_MOD_REVISION; + } + + @Override + public void update(IndexRuleBinding payload) throws BanyanDBException { + execute(() -> stub.update(BanyandbDatabase.IndexRuleBindingRegistryServiceUpdateRequest.newBuilder() + .setIndexRuleBinding(payload) + .build())); + } + + @Override + public boolean delete(String group, String name) throws BanyanDBException { + BanyandbDatabase.IndexRuleBindingRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.IndexRuleBindingRegistryServiceDeleteRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public IndexRuleBinding get(String group, String name) throws BanyanDBException { + BanyandbDatabase.IndexRuleBindingRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.IndexRuleBindingRegistryServiceGetRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + + return resp.getIndexRuleBinding(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.IndexRuleBindingRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.IndexRuleBindingRegistryServiceExistRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasIndexRuleBinding()).build(); + } + + @Override + public List list(String group) throws BanyanDBException { + BanyandbDatabase.IndexRuleBindingRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.IndexRuleBindingRegistryServiceListRequest.newBuilder() + .setGroup(group) + .build())); + + return resp.getIndexRuleBindingList(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/IndexRuleMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/IndexRuleMetadataRegistry.java new file mode 100644 index 000000000000..27cdcf61e04b --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/IndexRuleMetadataRegistry.java @@ -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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRule; +import org.apache.skywalking.banyandb.database.v1.IndexRuleRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class IndexRuleMetadataRegistry extends MetadataClient { + public IndexRuleMetadataRegistry(Channel channel) { + super(IndexRuleRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(IndexRule payload) throws BanyanDBException { + execute(() -> + stub.create(BanyandbDatabase.IndexRuleRegistryServiceCreateRequest.newBuilder() + .setIndexRule(payload) + .build())); + return DEFAULT_MOD_REVISION; + } + + @Override + public void update(IndexRule payload) throws BanyanDBException { + execute(() -> + stub.update(BanyandbDatabase.IndexRuleRegistryServiceUpdateRequest.newBuilder() + .setIndexRule(payload) + .build())); + } + + @Override + public boolean delete(String group, String name) throws BanyanDBException { + BanyandbDatabase.IndexRuleRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.IndexRuleRegistryServiceDeleteRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public IndexRule get(String group, String name) throws BanyanDBException { + BanyandbDatabase.IndexRuleRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.IndexRuleRegistryServiceGetRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + + return resp.getIndexRule(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.IndexRuleRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.IndexRuleRegistryServiceExistRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasIndexRule()).build(); + } + + @Override + public List list(String group) throws BanyanDBException { + BanyandbDatabase.IndexRuleRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.IndexRuleRegistryServiceListRequest.newBuilder() + .setGroup(group) + .build())); + + return resp.getIndexRuleList(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/MeasureMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/MeasureMetadataRegistry.java new file mode 100644 index 000000000000..1e3be1b421e0 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/MeasureMetadataRegistry.java @@ -0,0 +1,91 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Measure; +import org.apache.skywalking.banyandb.database.v1.MeasureRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class MeasureMetadataRegistry extends MetadataClient { + + public MeasureMetadataRegistry(Channel channel) { + super(MeasureRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(final Measure payload) throws BanyanDBException { + BanyandbDatabase.MeasureRegistryServiceCreateResponse resp = execute(() -> + stub.create(BanyandbDatabase.MeasureRegistryServiceCreateRequest.newBuilder() + .setMeasure(payload) + .build())); + return resp.getModRevision(); + } + + @Override + public void update(final Measure payload) throws BanyanDBException { + execute(() -> + stub.update(BanyandbDatabase.MeasureRegistryServiceUpdateRequest.newBuilder() + .setMeasure(payload) + .build())); + } + + @Override + public boolean delete(final String group, final String name) throws BanyanDBException { + BanyandbDatabase.MeasureRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.MeasureRegistryServiceDeleteRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public Measure get(final String group, final String name) throws BanyanDBException { + BanyandbDatabase.MeasureRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.MeasureRegistryServiceGetRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + + return resp.getMeasure(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.MeasureRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.MeasureRegistryServiceExistRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasMeasure()).build(); + } + + @Override + public List list(final String group) throws BanyanDBException { + BanyandbDatabase.MeasureRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.MeasureRegistryServiceListRequest.newBuilder() + .setGroup(group) + .build())); + + return resp.getMeasureList(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/PropertyMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/PropertyMetadataRegistry.java new file mode 100644 index 000000000000..ae543bc6aa59 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/PropertyMetadataRegistry.java @@ -0,0 +1,91 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Property; +import org.apache.skywalking.banyandb.database.v1.PropertyRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class PropertyMetadataRegistry extends MetadataClient { + + public PropertyMetadataRegistry(Channel channel) { + super(PropertyRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(final Property payload) throws BanyanDBException { + BanyandbDatabase.PropertyRegistryServiceCreateResponse resp = execute(() -> + stub.create(BanyandbDatabase.PropertyRegistryServiceCreateRequest.newBuilder() + .setProperty(payload) + .build())); + return resp.getModRevision(); + } + + @Override + public void update(final Property payload) throws BanyanDBException { + execute(() -> + stub.update(BanyandbDatabase.PropertyRegistryServiceUpdateRequest.newBuilder() + .setProperty(payload) + .build())); + } + + @Override + public boolean delete(final String group, final String name) throws BanyanDBException { + BanyandbDatabase.PropertyRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.PropertyRegistryServiceDeleteRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public Property get(final String group, final String name) throws BanyanDBException { + BanyandbDatabase.PropertyRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.PropertyRegistryServiceGetRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + + return resp.getProperty(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.PropertyRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.PropertyRegistryServiceExistRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasProperty()).build(); + } + + @Override + public List list(final String group) throws BanyanDBException { + BanyandbDatabase.PropertyRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.PropertyRegistryServiceListRequest.newBuilder() + .setGroup(group) + .build())); + + return resp.getPropertiesList(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/ResourceExist.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/ResourceExist.java new file mode 100644 index 000000000000..76d698b48df3 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/ResourceExist.java @@ -0,0 +1,29 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +import lombok.Builder; +import lombok.Getter; + +@Builder +@Getter +public class ResourceExist { + private final boolean hasGroup; + private final boolean hasResource; +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/Serializable.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/Serializable.java new file mode 100644 index 000000000000..d3a4856fbb9e --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/Serializable.java @@ -0,0 +1,34 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +/** + * Serializable provide serialize method to build a protobuf message. + * This is normally for inner types of metadata. + * + * @param

the produced class must be in Protobuf message type. + */ +public interface Serializable

{ + /** + * Serialize the object to the protobuf format + * + * @return protobuf representation + */ + P serialize(); +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/StreamMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/StreamMetadataRegistry.java new file mode 100644 index 000000000000..efcb66370715 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/StreamMetadataRegistry.java @@ -0,0 +1,91 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Stream; +import org.apache.skywalking.banyandb.database.v1.StreamRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class StreamMetadataRegistry extends MetadataClient { + + public StreamMetadataRegistry(Channel channel) { + super(StreamRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(Stream payload) throws BanyanDBException { + BanyandbDatabase.StreamRegistryServiceCreateResponse resp = execute(() -> + stub.create(BanyandbDatabase.StreamRegistryServiceCreateRequest.newBuilder() + .setStream(payload) + .build())); + return resp.getModRevision(); + } + + @Override + public void update(Stream payload) throws BanyanDBException { + execute(() -> + stub.update(BanyandbDatabase.StreamRegistryServiceUpdateRequest.newBuilder() + .setStream(payload) + .build())); + } + + @Override + public boolean delete(String group, String name) throws BanyanDBException { + BanyandbDatabase.StreamRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.StreamRegistryServiceDeleteRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public Stream get(String group, String name) throws BanyanDBException { + BanyandbDatabase.StreamRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.StreamRegistryServiceGetRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + + return resp.getStream(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.StreamRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.StreamRegistryServiceExistRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasStream()).build(); + } + + @Override + public List list(String group) throws BanyanDBException { + BanyandbDatabase.StreamRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.StreamRegistryServiceListRequest.newBuilder() + .setGroup(group) + .build())); + + return resp.getStreamList(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/TopNAggregationMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/TopNAggregationMetadataRegistry.java new file mode 100644 index 000000000000..f5813e1caccf --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/TopNAggregationMetadataRegistry.java @@ -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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TopNAggregation; +import org.apache.skywalking.banyandb.database.v1.TopNAggregationRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class TopNAggregationMetadataRegistry extends MetadataClient { + public TopNAggregationMetadataRegistry(Channel channel) { + super(TopNAggregationRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(TopNAggregation payload) throws BanyanDBException { + execute(() -> + stub.create(BanyandbDatabase.TopNAggregationRegistryServiceCreateRequest.newBuilder() + .setTopNAggregation(payload) + .build())); + return DEFAULT_MOD_REVISION; + } + + @Override + public void update(TopNAggregation payload) throws BanyanDBException { + execute(() -> + stub.update(BanyandbDatabase.TopNAggregationRegistryServiceUpdateRequest.newBuilder() + .setTopNAggregation(payload) + .build())); + } + + @Override + public boolean delete(String group, String name) throws BanyanDBException { + BanyandbDatabase.TopNAggregationRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.TopNAggregationRegistryServiceDeleteRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public TopNAggregation get(String group, String name) throws BanyanDBException { + BanyandbDatabase.TopNAggregationRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.TopNAggregationRegistryServiceGetRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + + return resp.getTopNAggregation(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.TopNAggregationRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.TopNAggregationRegistryServiceExistRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasTopNAggregation()).build(); + } + + @Override + public List list(String group) throws BanyanDBException { + BanyandbDatabase.TopNAggregationRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.TopNAggregationRegistryServiceListRequest.newBuilder() + .setGroup(group) + .build())); + + return resp.getTopNAggregationList(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/TraceMetadataRegistry.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/TraceMetadataRegistry.java new file mode 100644 index 000000000000..64fc61afe008 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/metadata/TraceMetadataRegistry.java @@ -0,0 +1,91 @@ +/* + * 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.library.banyandb.v1.client.metadata; + +import io.grpc.Channel; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Trace; +import org.apache.skywalking.banyandb.database.v1.TraceRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.MetadataClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; + +public class TraceMetadataRegistry extends MetadataClient { + + public TraceMetadataRegistry(Channel channel) { + super(TraceRegistryServiceGrpc.newBlockingStub(channel)); + } + + @Override + public long create(Trace payload) throws BanyanDBException { + BanyandbDatabase.TraceRegistryServiceCreateResponse resp = execute(() -> + stub.create(BanyandbDatabase.TraceRegistryServiceCreateRequest.newBuilder() + .setTrace(payload) + .build())); + return resp.getModRevision(); + } + + @Override + public void update(Trace payload) throws BanyanDBException { + execute(() -> + stub.update(BanyandbDatabase.TraceRegistryServiceUpdateRequest.newBuilder() + .setTrace(payload) + .build())); + } + + @Override + public boolean delete(String group, String name) throws BanyanDBException { + BanyandbDatabase.TraceRegistryServiceDeleteResponse resp = execute(() -> + stub.delete(BanyandbDatabase.TraceRegistryServiceDeleteRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return resp != null && resp.getDeleted(); + } + + @Override + public Trace get(String group, String name) throws BanyanDBException { + BanyandbDatabase.TraceRegistryServiceGetResponse resp = execute(() -> + stub.get(BanyandbDatabase.TraceRegistryServiceGetRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + + return resp.getTrace(); + } + + @Override + public ResourceExist exist(String group, String name) throws BanyanDBException { + BanyandbDatabase.TraceRegistryServiceExistResponse resp = execute(() -> + stub.exist(BanyandbDatabase.TraceRegistryServiceExistRequest.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder().setGroup(group).setName(name).build()) + .build())); + return ResourceExist.builder().hasGroup(resp.getHasGroup()).hasResource(resp.getHasTrace()).build(); + } + + @Override + public List list(String group) throws BanyanDBException { + BanyandbDatabase.TraceRegistryServiceListResponse resp = execute(() -> + stub.list(BanyandbDatabase.TraceRegistryServiceListRequest.newBuilder() + .setGroup(group) + .build())); + + return resp.getTraceList(); + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/CopyOnWriteMap.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/CopyOnWriteMap.java new file mode 100644 index 000000000000..9a9f74511096 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/CopyOnWriteMap.java @@ -0,0 +1,181 @@ +/* + * 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. + * + */ + +/* + * Copyright 2015 Confluent Inc. + * + * Licensed 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. + */ + +/* + * Original license: + * + * 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.library.banyandb.v1.client.util; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentMap; + +/** + * A simple read-optimized map implementation that synchronizes only writes and does a full copy on + * each modification + */ +public class CopyOnWriteMap implements ConcurrentMap { + + private volatile Map map; + + public CopyOnWriteMap() { + this.map = Collections.emptyMap(); + } + + public CopyOnWriteMap(Map map) { + this.map = Collections.unmodifiableMap(map); + } + + @Override + public boolean containsKey(Object k) { + return map.containsKey(k); + } + + @Override + public boolean containsValue(Object v) { + return map.containsValue(v); + } + + @Override + public Set> entrySet() { + return map.entrySet(); + } + + @Override + public V get(Object k) { + return map.get(k); + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public Set keySet() { + return map.keySet(); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public Collection values() { + return map.values(); + } + + @Override + public synchronized void clear() { + this.map = Collections.emptyMap(); + } + + @Override + public synchronized V put(K k, V v) { + Map copy = new HashMap(this.map); + V prev = copy.put(k, v); + this.map = Collections.unmodifiableMap(copy); + return prev; + } + + @Override + public synchronized void putAll(Map entries) { + Map copy = new HashMap(this.map); + copy.putAll(entries); + this.map = Collections.unmodifiableMap(copy); + } + + @Override + public synchronized V remove(Object key) { + Map copy = new HashMap(this.map); + V prev = copy.remove(key); + this.map = Collections.unmodifiableMap(copy); + return prev; + } + + @Override + public synchronized V putIfAbsent(K k, V v) { + if (!containsKey(k)) { + return put(k, v); + } else { + return get(k); + } + } + + @Override + public synchronized boolean remove(Object k, Object v) { + if (containsKey(k) && get(k).equals(v)) { + remove(k); + return true; + } else { + return false; + } + } + + @Override + public synchronized boolean replace(K k, V original, V replacement) { + if (containsKey(k) && get(k).equals(original)) { + put(k, replacement); + return true; + } else { + return false; + } + } + + @Override + public synchronized V replace(K k, V v) { + if (containsKey(k)) { + return put(k, v); + } else { + return null; + } + } + +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/IgnoreHashEquals.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/IgnoreHashEquals.java new file mode 100644 index 000000000000..d33e0a0c3e96 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/IgnoreHashEquals.java @@ -0,0 +1,32 @@ +/* + * 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.library.banyandb.v1.client.util; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.SOURCE; + +@Retention(SOURCE) +@Target({METHOD, PARAMETER, FIELD}) +public @interface IgnoreHashEquals { +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/PrivateKeyUtil.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/PrivateKeyUtil.java new file mode 100644 index 000000000000..76ff08d33892 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/PrivateKeyUtil.java @@ -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.library.banyandb.v1.client.util; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Base64; + +/** + * Util intends to parse PKCS#1 and PKCS#8 at same time. + */ +public class PrivateKeyUtil { + private static final String PKCS_1_PEM_HEADER = "-----BEGIN RSA PRIVATE KEY-----"; + private static final String PKCS_1_PEM_FOOTER = "-----END RSA PRIVATE KEY-----"; + private static final String PKCS_8_PEM_HEADER = "-----BEGIN PRIVATE KEY-----"; + private static final String PKCS_8_PEM_FOOTER = "-----END PRIVATE KEY-----"; + + /** + * Load a RSA decryption key from a file (PEM or DER). + */ + public static InputStream loadDecryptionKey(String keyFilePath) throws IOException { + byte[] keyDataBytes = Files.readAllBytes(Paths.get(keyFilePath)); + String keyDataString = new String(keyDataBytes, StandardCharsets.UTF_8); + + if (keyDataString.contains(PKCS_1_PEM_HEADER)) { + // OpenSSL / PKCS#1 Base64 PEM encoded file + keyDataString = keyDataString.replace(PKCS_1_PEM_HEADER, ""); + keyDataString = keyDataString.replace(PKCS_1_PEM_FOOTER, ""); + keyDataString = keyDataString.replace("\n", ""); + return readPkcs1PrivateKey(Base64.getDecoder().decode(keyDataString)); + } + + return new ByteArrayInputStream(keyDataString.getBytes()); + } + + /** + * Create a InputStream instance from raw PKCS#1 bytes. Raw Java API can't recognize ASN.1 format, so we should + * convert it into a pkcs#8 format Java can understand. + */ + private static InputStream readPkcs1PrivateKey(byte[] pkcs1Bytes) { + int pkcs1Length = pkcs1Bytes.length; + int totalLength = pkcs1Length + 22; + byte[] pkcs8Header = new byte[]{ + 0x30, (byte) 0x82, (byte) ((totalLength >> 8) & 0xff), (byte) (totalLength & 0xff), // Sequence + total length + 0x2, 0x1, 0x0, // Integer (0) + 0x30, 0xD, 0x6, 0x9, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0xD, 0x1, 0x1, 0x1, 0x5, 0x0, // Sequence: 1.2.840.113549.1.1.1, NULL + 0x4, (byte) 0x82, (byte) ((pkcs1Length >> 8) & 0xff), (byte) (pkcs1Length & 0xff) // Octet string + length + }; + StringBuilder pkcs8 = new StringBuilder(PKCS_8_PEM_HEADER); + pkcs8.append("\n").append(new String(Base64.getEncoder().encode(join(pkcs8Header, pkcs1Bytes)))); + pkcs8.append("\n").append(PKCS_8_PEM_FOOTER); + return new ByteArrayInputStream(pkcs8.toString().getBytes()); + } + + private static byte[] join(byte[] byteArray1, byte[] byteArray2) { + byte[] bytes = new byte[byteArray1.length + byteArray2.length]; + System.arraycopy(byteArray1, 0, bytes, 0, byteArray1.length); + System.arraycopy(byteArray2, 0, bytes, byteArray1.length, byteArray2.length); + return bytes; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/StatusUtil.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/StatusUtil.java new file mode 100644 index 000000000000..b15ec39cc6f7 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/StatusUtil.java @@ -0,0 +1,42 @@ +/* + * 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.library.banyandb.v1.client.util; + +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; + +/** + * Status is a utility class for converting between strings and Status enums. + */ +public class StatusUtil { + + /** + * Convert a Status enum to a string. + * + * @param statusString the string to convert + * @return the Status enum + */ + public static BanyandbModel.Status convertStringToStatus(String statusString) { + try { + return BanyandbModel.Status.valueOf(statusString); + } catch (IllegalArgumentException e) { + // Return a specific enum value for unknown strings + return BanyandbModel.Status.STATUS_UNSPECIFIED; + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/TimeUtils.java b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/TimeUtils.java new file mode 100644 index 000000000000..d65a5318d263 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/util/TimeUtils.java @@ -0,0 +1,50 @@ +/* + * 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.library.banyandb.v1.client.util; + +import com.google.protobuf.Timestamp; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +public class TimeUtils { + public static ZonedDateTime parseTimestamp(Timestamp ts) { + return Instant.ofEpochSecond(ts.getSeconds(), ts.getNanos()).atZone(ZoneId.systemDefault()); + } + + public static Timestamp buildTimestamp(ZonedDateTime zdt) { + if (zdt == null) { + return null; + } + return Timestamp.newBuilder() + .setSeconds(zdt.toInstant().getEpochSecond()) + .setNanos(zdt.toInstant().getNano()) + .build(); + } + + public static Timestamp fromEpochNanos(long nanos) { + long seconds = nanos / 1000_000_000; + int nanosInt = (int) (nanos - seconds * 1000_000_000); + int res = nanosInt % 1000_000; + return Timestamp.newBuilder() + .setSeconds(seconds) + .setNanos(nanosInt - res) + .build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/main/proto b/oap-server/server-library/library-banyandb-client/src/main/proto new file mode 160000 index 000000000000..b1c87663e577 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/main/proto @@ -0,0 +1 @@ +Subproject commit b1c87663e57796402736a5f52dd3b4ca8d981e89 diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/AbstractBanyanDBClientTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/AbstractBanyanDBClientTest.java new file mode 100644 index 000000000000..3f59ab12c64a --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/AbstractBanyanDBClientTest.java @@ -0,0 +1,380 @@ +/* + * 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.library.banyandb.v1.client; + +import io.grpc.BindableService; +import io.grpc.ForwardingServerBuilder; +import io.grpc.ManagedChannel; +import io.grpc.Server; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.stub.StreamObserver; +import io.grpc.util.MutableHandlerRegistry; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.IndexRuleBindingRegistryServiceGrpc; +import org.apache.skywalking.banyandb.database.v1.IndexRuleRegistryServiceGrpc; +import org.apache.skywalking.banyandb.database.v1.MeasureRegistryServiceGrpc; +import org.apache.skywalking.banyandb.database.v1.StreamRegistryServiceGrpc; +import org.apache.skywalking.banyandb.database.v1.TopNAggregationRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.util.TimeUtils; +import java.io.IOException; +import java.time.ZonedDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import static org.mockito.AdditionalAnswers.delegatesTo; +import static org.mockito.Mockito.mock; + +public class AbstractBanyanDBClientTest { + // play as an in-memory registry + protected Map indexRuleBindingRegistry; + + private final IndexRuleBindingRegistryServiceGrpc.IndexRuleBindingRegistryServiceImplBase indexRuleBindingServiceImpl = + mock(IndexRuleBindingRegistryServiceGrpc.IndexRuleBindingRegistryServiceImplBase.class, delegatesTo( + new IndexRuleBindingRegistryServiceGrpc.IndexRuleBindingRegistryServiceImplBase() { + @Override + public void create(BanyandbDatabase.IndexRuleBindingRegistryServiceCreateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.IndexRuleBinding s = request.getIndexRuleBinding().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .build(); + indexRuleBindingRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.IndexRuleBindingRegistryServiceCreateResponse.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public void update(BanyandbDatabase.IndexRuleBindingRegistryServiceUpdateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.IndexRuleBinding s = request.getIndexRuleBinding().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .build(); + indexRuleBindingRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.IndexRuleBindingRegistryServiceUpdateResponse.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public void delete(BanyandbDatabase.IndexRuleBindingRegistryServiceDeleteRequest request, StreamObserver responseObserver) { + BanyandbDatabase.IndexRuleBinding oldIndexRuleBinding = indexRuleBindingRegistry.remove(request.getMetadata().getName()); + responseObserver.onNext(BanyandbDatabase.IndexRuleBindingRegistryServiceDeleteResponse.newBuilder() + .setDeleted(oldIndexRuleBinding != null) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void get(BanyandbDatabase.IndexRuleBindingRegistryServiceGetRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.IndexRuleBindingRegistryServiceGetResponse.newBuilder() + .setIndexRuleBinding(indexRuleBindingRegistry.get(request.getMetadata().getName())) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void list(BanyandbDatabase.IndexRuleBindingRegistryServiceListRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.IndexRuleBindingRegistryServiceListResponse.newBuilder() + .addAllIndexRuleBinding(indexRuleBindingRegistry.values()) + .build()); + responseObserver.onCompleted(); + } + })); + + // play as an in-memory registry + protected Map indexRuleRegistry; + + private final IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase indexRuleServiceImpl = + mock(IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase.class, delegatesTo( + new IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase() { + @Override + public void create(BanyandbDatabase.IndexRuleRegistryServiceCreateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.IndexRule s = request.getIndexRule().toBuilder().setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .build(); + indexRuleRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.IndexRuleRegistryServiceCreateResponse.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public void update(BanyandbDatabase.IndexRuleRegistryServiceUpdateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.IndexRule s = request.getIndexRule().toBuilder().setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .build(); + indexRuleRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.IndexRuleRegistryServiceUpdateResponse.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public void delete(BanyandbDatabase.IndexRuleRegistryServiceDeleteRequest request, StreamObserver responseObserver) { + BanyandbDatabase.IndexRule oldIndexRule = indexRuleRegistry.remove(request.getMetadata().getName()); + responseObserver.onNext(BanyandbDatabase.IndexRuleRegistryServiceDeleteResponse.newBuilder() + .setDeleted(oldIndexRule != null) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void get(BanyandbDatabase.IndexRuleRegistryServiceGetRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.IndexRuleRegistryServiceGetResponse.newBuilder() + .setIndexRule(indexRuleRegistry.get(request.getMetadata().getName())) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void list(BanyandbDatabase.IndexRuleRegistryServiceListRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.IndexRuleRegistryServiceListResponse.newBuilder() + .addAllIndexRule(indexRuleRegistry.values()) + .build()); + responseObserver.onCompleted(); + } + })); + + // stream registry + protected Map streamRegistry; + + private final StreamRegistryServiceGrpc.StreamRegistryServiceImplBase streamRegistryServiceImpl = + mock(StreamRegistryServiceGrpc.StreamRegistryServiceImplBase.class, delegatesTo( + new StreamRegistryServiceGrpc.StreamRegistryServiceImplBase() { + private final AtomicLong revisionGenerator = new AtomicLong(0); + + @Override + public void create(BanyandbDatabase.StreamRegistryServiceCreateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.Stream s = request.getStream().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .setMetadata(request.getStream().getMetadata().toBuilder() + .setModRevision(revisionGenerator.incrementAndGet()) + .build()) + .build(); + streamRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.StreamRegistryServiceCreateResponse.newBuilder().setModRevision(s.getMetadata().getModRevision()).build()); + responseObserver.onCompleted(); + } + + @Override + public void update(BanyandbDatabase.StreamRegistryServiceUpdateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.Stream s = request.getStream().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .setMetadata(request.getStream().getMetadata().toBuilder() + .setModRevision(revisionGenerator.incrementAndGet()) + .build()) + .build(); + streamRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.StreamRegistryServiceUpdateResponse.newBuilder().setModRevision(s.getMetadata().getModRevision()).build()); + responseObserver.onCompleted(); + } + + @Override + public void delete(BanyandbDatabase.StreamRegistryServiceDeleteRequest request, StreamObserver responseObserver) { + BanyandbDatabase.Stream oldStream = streamRegistry.remove(request.getMetadata().getName()); + responseObserver.onNext(BanyandbDatabase.StreamRegistryServiceDeleteResponse.newBuilder() + .setDeleted(oldStream != null) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void get(BanyandbDatabase.StreamRegistryServiceGetRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.StreamRegistryServiceGetResponse.newBuilder() + .setStream(streamRegistry.get(request.getMetadata().getName())) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void list(BanyandbDatabase.StreamRegistryServiceListRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.StreamRegistryServiceListResponse.newBuilder() + .addAllStream(streamRegistry.values()) + .build()); + responseObserver.onCompleted(); + } + })); + + // measure registry + protected Map measureRegistry; + + private final MeasureRegistryServiceGrpc.MeasureRegistryServiceImplBase measureRegistryServiceImpl = + mock(MeasureRegistryServiceGrpc.MeasureRegistryServiceImplBase.class, delegatesTo( + new MeasureRegistryServiceGrpc.MeasureRegistryServiceImplBase() { + private final AtomicLong revisionGenerator = new AtomicLong(0); + + @Override + public void create(BanyandbDatabase.MeasureRegistryServiceCreateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.Measure s = request.getMeasure().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .setMetadata(request.getMeasure().getMetadata().toBuilder() + .setModRevision(revisionGenerator.incrementAndGet()) + .build()) + .build(); + measureRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.MeasureRegistryServiceCreateResponse.newBuilder().setModRevision(s.getMetadata().getModRevision()).build()); + responseObserver.onCompleted(); + } + + @Override + public void update(BanyandbDatabase.MeasureRegistryServiceUpdateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.Measure s = request.getMeasure().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .setMetadata(request.getMeasure().getMetadata().toBuilder() + .setModRevision(revisionGenerator.incrementAndGet()) + .build()) + .build(); + measureRegistry.put(s.getMetadata().getName(), s); + responseObserver.onNext(BanyandbDatabase.MeasureRegistryServiceUpdateResponse.newBuilder().setModRevision(s.getMetadata().getModRevision()).build()); + responseObserver.onCompleted(); + } + + @Override + public void delete(BanyandbDatabase.MeasureRegistryServiceDeleteRequest request, StreamObserver responseObserver) { + BanyandbDatabase.Measure oldMeasure = measureRegistry.remove(request.getMetadata().getName()); + responseObserver.onNext(BanyandbDatabase.MeasureRegistryServiceDeleteResponse.newBuilder() + .setDeleted(oldMeasure != null) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void get(BanyandbDatabase.MeasureRegistryServiceGetRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.MeasureRegistryServiceGetResponse.newBuilder() + .setMeasure(measureRegistry.get(request.getMetadata().getName())) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void list(BanyandbDatabase.MeasureRegistryServiceListRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.MeasureRegistryServiceListResponse.newBuilder() + .addAllMeasure(measureRegistry.values()) + .build()); + responseObserver.onCompleted(); + } + })); + + // measure registry + protected Map topNAggregationRegistry; + + private final TopNAggregationRegistryServiceGrpc.TopNAggregationRegistryServiceImplBase topNAggregationRegistryServiceImpl = + mock(TopNAggregationRegistryServiceGrpc.TopNAggregationRegistryServiceImplBase.class, delegatesTo( + new TopNAggregationRegistryServiceGrpc.TopNAggregationRegistryServiceImplBase() { + @Override + public void create(BanyandbDatabase.TopNAggregationRegistryServiceCreateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.TopNAggregation aggr = request.getTopNAggregation().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .build(); + topNAggregationRegistry.put(aggr.getMetadata().getName(), aggr); + responseObserver.onNext(BanyandbDatabase.TopNAggregationRegistryServiceCreateResponse.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public void update(BanyandbDatabase.TopNAggregationRegistryServiceUpdateRequest request, StreamObserver responseObserver) { + BanyandbDatabase.TopNAggregation aggr = request.getTopNAggregation().toBuilder() + .setUpdatedAt(TimeUtils.buildTimestamp(ZonedDateTime.now())) + .build(); + topNAggregationRegistry.put(aggr.getMetadata().getName(), aggr); + responseObserver.onNext(BanyandbDatabase.TopNAggregationRegistryServiceUpdateResponse.newBuilder().build()); + responseObserver.onCompleted(); + } + + @Override + public void delete(BanyandbDatabase.TopNAggregationRegistryServiceDeleteRequest request, StreamObserver responseObserver) { + BanyandbDatabase.TopNAggregation oldMeasure = topNAggregationRegistry.remove(request.getMetadata().getName()); + responseObserver.onNext(BanyandbDatabase.TopNAggregationRegistryServiceDeleteResponse.newBuilder() + .setDeleted(oldMeasure != null) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void get(BanyandbDatabase.TopNAggregationRegistryServiceGetRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.TopNAggregationRegistryServiceGetResponse.newBuilder() + .setTopNAggregation(topNAggregationRegistry.get(request.getMetadata().getName())) + .build()); + responseObserver.onCompleted(); + } + + @Override + public void list(BanyandbDatabase.TopNAggregationRegistryServiceListRequest request, StreamObserver responseObserver) { + responseObserver.onNext(BanyandbDatabase.TopNAggregationRegistryServiceListResponse.newBuilder() + .addAllTopNAggregation(topNAggregationRegistry.values()) + .build()); + responseObserver.onCompleted(); + } + })); + + protected final MutableHandlerRegistry serviceRegistry = new MutableHandlerRegistry(); + + protected BanyanDBClient client; + + protected ManagedChannel channel; + + protected void setUp(SetupFunction... setUpFunctions) throws IOException { + indexRuleRegistry = new HashMap<>(); + serviceRegistry.addService(indexRuleServiceImpl); + + indexRuleBindingRegistry = new HashMap<>(); + serviceRegistry.addService(indexRuleBindingServiceImpl); + indexRuleBindingRegistry = new HashMap<>(); + + // Generate a unique in-process server name. + String serverName = InProcessServerBuilder.generateName(); + + // Create a server, add service, start, and register for automatic graceful shutdown. + InProcessServerBuilder serverBuilder = InProcessServerBuilder + .forName(serverName).directExecutor() + .fallbackHandlerRegistry(serviceRegistry); + for (final SetupFunction func : setUpFunctions) { + func.apply(serverBuilder); + } + final Server s = serverBuilder.build(); + s.start(); + this.channel = InProcessChannelBuilder.forName(serverName).directExecutor().build(); + + client = new BanyanDBClient(String.format("127.0.0.1:%d", s.getPort())); + client.connect(this.channel); + } + + protected interface SetupFunction { + void apply(ForwardingServerBuilder builder); + } + + protected SetupFunction bindStreamRegistry() { + return b -> { + AbstractBanyanDBClientTest.this.streamRegistry = new HashMap<>(); + serviceRegistry.addService(streamRegistryServiceImpl); + }; + } + + protected SetupFunction bindService(final BindableService bindableService) { + return b -> serviceRegistry.addService(bindableService); + } + + protected SetupFunction bindMeasureRegistry() { + return b -> { + AbstractBanyanDBClientTest.this.measureRegistry = new HashMap<>(); + serviceRegistry.addService(measureRegistryServiceImpl); + }; + } + + protected SetupFunction bindTopNAggregationRegistry() { + return b -> { + AbstractBanyanDBClientTest.this.topNAggregationRegistry = new HashMap<>(); + serviceRegistry.addService(topNAggregationRegistryServiceImpl); + }; + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClientTestCI.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClientTestCI.java new file mode 100644 index 000000000000..fdd826ca0192 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClientTestCI.java @@ -0,0 +1,104 @@ +/* + * 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.library.banyandb.v1.client; + +import lombok.extern.slf4j.Slf4j; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.oap.server.library.it.ITVersions; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; +import java.io.IOException; + +@Slf4j +@Testcontainers +public class BanyanDBClientTestCI { + private static final String REGISTRY = "ghcr.io"; + private static final String IMAGE_NAME = "apache/skywalking-banyandb"; + private static final String TAG = ITVersions.get("SW_BANYANDB_COMMIT"); + + private static final String IMAGE = REGISTRY + "/" + IMAGE_NAME + ":" + TAG; + + protected static final int GRPC_PORT = 17912; + protected static final int HTTP_PORT = 17913; + + @Container + public GenericContainer banyanDB = new GenericContainer<>( + DockerImageName.parse(IMAGE)) + .withCommand("standalone", "--stream-root-path", "/tmp/banyandb-stream-data", + "--measure-root-path", "/tmp/banyand-measure-data") + .withExposedPorts(GRPC_PORT, HTTP_PORT) + .waitingFor(Wait.forHttp("/api/healthz").forPort(HTTP_PORT)); + + protected BanyanDBClient client; + + protected void setUpConnection() throws IOException { + log.info("create BanyanDB client and try to connect"); + client = new BanyanDBClient(String.format("%s:%d", banyanDB.getHost(), banyanDB.getMappedPort(GRPC_PORT))); + client.connect(); + } + + protected void closeClient() throws IOException { + if (this.client != null) { + this.client.close(); + } + } + + protected BanyandbCommon.Group buildStreamGroup() { + return BanyandbCommon.Group.newBuilder().setMetadata(BanyandbCommon.Metadata.newBuilder().setName("sw_record")) + .setCatalog(BanyandbCommon.Catalog.CATALOG_STREAM) + .setResourceOpts(BanyandbCommon.ResourceOpts.newBuilder() + .setShardNum(2) + .setSegmentInterval( + BanyandbCommon.IntervalRule.newBuilder() + .setUnit( + BanyandbCommon.IntervalRule.Unit.UNIT_DAY) + .setNum( + 1)) + .setTtl( + BanyandbCommon.IntervalRule.newBuilder() + .setUnit( + BanyandbCommon.IntervalRule.Unit.UNIT_DAY) + .setNum( + 3))) + .build(); + } + + protected BanyandbCommon.Group buildMeasureGroup() { + return BanyandbCommon.Group.newBuilder().setMetadata(BanyandbCommon.Metadata.newBuilder().setName("sw_metric")) + .setCatalog(BanyandbCommon.Catalog.CATALOG_MEASURE) + .setResourceOpts(BanyandbCommon.ResourceOpts.newBuilder() + .setShardNum(2) + .setSegmentInterval( + BanyandbCommon.IntervalRule.newBuilder() + .setUnit( + BanyandbCommon.IntervalRule.Unit.UNIT_DAY) + .setNum( + 1)) + .setTtl( + BanyandbCommon.IntervalRule.newBuilder() + .setUnit( + BanyandbCommon.IntervalRule.Unit.UNIT_DAY) + .setNum( + 7))) + .build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBAuthTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBAuthTest.java new file mode 100644 index 000000000000..d2d6883607d0 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBAuthTest.java @@ -0,0 +1,110 @@ +/* + * 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.library.banyandb.v1.client; + +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.UnauthenticatedException; +import org.apache.skywalking.oap.server.library.it.ITVersions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.DockerImageName; +import org.testcontainers.utility.MountableFile; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermissions; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; + +public class ITBanyanDBAuthTest extends BanyanDBClientTestCI { + private static final String REGISTRY = "ghcr.io"; + private static final String IMAGE_NAME = "apache/skywalking-banyandb"; + private static final String TAG = ITVersions.get("SW_BANYANDB_COMMIT"); + + private static final String IMAGE = REGISTRY + "/" + IMAGE_NAME + ":" + TAG; + + protected static final int GRPC_PORT = 17912; + protected static final int HTTP_PORT = 17913; + + public static GenericContainer DB; + + @BeforeAll + public static void init() throws Exception { + // Step 1: prepare config file with 0600 permissions + Path tempConfigPath = Files.createTempFile("bydb_server_config", ".yaml"); + Files.write( + tempConfigPath, Files.readAllBytes( + Paths.get(ITBanyanDBAuthTest.class.getClassLoader().getResource("config.yaml").toURI())) + ); + Files.setPosixFilePermissions(tempConfigPath, PosixFilePermissions.fromString("rw-------")); + + // Step 2: create container + DB = new GenericContainer<>(DockerImageName.parse(IMAGE)) + .withCopyFileToContainer( + MountableFile.forHostPath(tempConfigPath), + "/tmp/bydb_server_config.yaml" + ) + .withCommand( + "standalone", + "--auth-config-file", "/tmp/bydb_server_config.yaml" + ) + .withExposedPorts(GRPC_PORT, HTTP_PORT) + .waitingFor(Wait.forHttp("/api/healthz").forPort(HTTP_PORT)); + DB.start(); + } + + @Test + public void testAuthWithCorrect() throws IOException { + BanyanDBClient client = createClient("admin", "123456"); + client.connect(); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + // get api version + client.getAPIVersion(); + // list all groups + List groupList = client.findGroups(); + assertEquals(0, groupList.size()); + }); + client.close(); + } + + @Test + public void testAuthWithWrong() throws IOException { + BanyanDBClient client = createClient("admin", "123456" + "wrong"); + client.connect(); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + assertThrows(UnauthenticatedException.class, client::getAPIVersion); + }); + client.close(); + } + + private BanyanDBClient createClient(String username, String password) { + Options options = new Options(); + options.setUsername(username); + options.setPassword(password); + String url = String.format("%s:%d", DB.getHost(), DB.getMappedPort(GRPC_PORT)); + return new BanyanDBClient(new String[] {url}, options); + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBCommonTests.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBCommonTests.java new file mode 100644 index 000000000000..11b9abb242dd --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBCommonTests.java @@ -0,0 +1,50 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.base.Strings; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import java.io.IOException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +public class ITBanyanDBCommonTests extends BanyanDBClientTestCI { + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void test_GetAPIVersion() throws BanyanDBException { + BanyandbCommon.APIVersion version = this.client.getAPIVersion(); + assertEquals("0.9", version.getVersion()); + assertFalse(Strings.isNullOrEmpty(version.getRevision())); + } + +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBMeasureQueryTests.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBMeasureQueryTests.java new file mode 100644 index 000000000000..faeb527f97b5 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBMeasureQueryTests.java @@ -0,0 +1,183 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Group; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Catalog; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.IntervalRule; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.ResourceOpts; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.CompressionMethod; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.EncodingMethod; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Entity; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.FieldSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.FieldType; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Measure; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagFamilySpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; +import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Duration; +import java.io.IOException; +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; + +public class ITBanyanDBMeasureQueryTests extends BanyanDBClientTestCI { + + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + Group expectedGroup = buildGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + Measure expectedMeasure = buildMeasure(); + client.define(expectedMeasure); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testMeasureQuery() throws BanyanDBException, ExecutionException, InterruptedException, TimeoutException { + // try to write a metrics + Instant now = Instant.now(); + Instant begin = now.minus(15, ChronoUnit.MINUTES); + + MeasureWrite measureWrite = client.createMeasureWrite("sw_metric", "service_cpm_minute", now.toEpochMilli()); + measureWrite.tag("storage-only", "entity_id", TagAndValue.stringTagValue("entity_1")) + .field("total", TagAndValue.longFieldValue(100)) + .field("value", TagAndValue.longFieldValue(1)); + StreamObserver writeObserver + = client.getMeasureServiceStub().write(new StreamObserver() { + @Override + public void onNext(BanyandbMeasure.WriteResponse writeResponse) { + assertEquals(BanyandbModel.Status.STATUS_SUCCEED.name(), writeResponse.getStatus()); + } + + @Override + public void onError(Throwable throwable) { + fail("write failed: " + throwable.getMessage()); + } + + @Override + public void onCompleted() { + + } + }); + try { + writeObserver.onNext(measureWrite.build()); + + } finally { + writeObserver.onCompleted(); + } + + MeasureQuery query = new MeasureQuery( + Lists.newArrayList("sw_metric"), "service_cpm_minute", + new TimestampRange(begin.toEpochMilli(), now.plus(1, ChronoUnit.MINUTES).toEpochMilli()), + ImmutableMap.of("entity_id", "storage-only"), + ImmutableSet.of("total") + ); // fields + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + MeasureQueryResponse resp = client.query(query); + assertNotNull(resp); + assertEquals(1, resp.size()); + }); + } + + private Group buildGroup() { + return Group.newBuilder().setMetadata(Metadata.newBuilder().setName("sw_metric")) + .setCatalog(Catalog.CATALOG_MEASURE) + .setResourceOpts(ResourceOpts.newBuilder() + .setShardNum(2) + .setSegmentInterval( + IntervalRule.newBuilder() + .setUnit( + IntervalRule.Unit.UNIT_DAY) + .setNum( + 1)) + .setTtl( + IntervalRule.newBuilder() + .setUnit( + IntervalRule.Unit.UNIT_DAY) + .setNum( + 7))) + .build(); + } + + private Measure buildMeasure() { + Measure.Builder builder = Measure.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_metric") + .setName("service_cpm_minute")) + .setInterval(Duration.ofMinutes(1).format()) + .setEntity(Entity.newBuilder().addTagNames("entity_id")) + .addTagFamilies( + TagFamilySpec.newBuilder() + .setName("default") + .addTags( + TagSpec.newBuilder() + .setName("entity_id") + .setType( + TagType.TAG_TYPE_STRING)) + .addTags( + TagSpec.newBuilder() + .setName("scope") + .setType( + TagType.TAG_TYPE_STRING))) + .addFields( + FieldSpec.newBuilder() + .setName("total") + .setFieldType( + FieldType.FIELD_TYPE_INT) + .setCompressionMethod( + CompressionMethod.COMPRESSION_METHOD_ZSTD) + .setEncodingMethod( + EncodingMethod.ENCODING_METHOD_GORILLA)) + .addFields( + FieldSpec.newBuilder() + .setName("value") + .setFieldType( + FieldType.FIELD_TYPE_INT) + .setCompressionMethod( + CompressionMethod.COMPRESSION_METHOD_ZSTD) + .setEncodingMethod( + EncodingMethod.ENCODING_METHOD_GORILLA)); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBPropertyTests.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBPropertyTests.java new file mode 100644 index 000000000000..1a982157171d --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBPropertyTests.java @@ -0,0 +1,238 @@ +/* + * 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.library.banyandb.v1.client; + +import org.apache.skywalking.banyandb.model.v1.BanyandbModel.Tag; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel.TagValue; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel.Str; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Group; +import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.Property; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; + +public class ITBanyanDBPropertyTests extends BanyanDBClientTestCI { + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + Group expectedGroup = + Group.newBuilder().setMetadata(Metadata.newBuilder() + .setName("default")) + .setCatalog(BanyandbCommon.Catalog.CATALOG_PROPERTY) + .setResourceOpts(BanyandbCommon.ResourceOpts.newBuilder() + .setShardNum(2)) + .build(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Property expectedProperty = + org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Property.newBuilder() + .setMetadata( + Metadata.newBuilder() + .setGroup("default") + .setName("sw") + .build()) + .addTags( + TagSpec.newBuilder() + .setName("name") + .setType( + TagType.TAG_TYPE_STRING)) + .build(); + client.define(expectedProperty); + assertNotNull(expectedProperty); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void test_PropertyCreateAndGet() throws BanyanDBException { + Property property = buildProperty("default", "sw", "ui_template").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("hello")))).build(); + PropertyStore store = new PropertyStore(client.getChannel()); + assertTrue(store.apply(property).getCreated()); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + BanyandbProperty.QueryResponse resp = client.query(BanyandbProperty.QueryRequest.newBuilder() + .addGroups("default") + .setName("sw") + .addIds("ui_template") + .build()); + assertEquals(1, resp.getPropertiesCount()); + Property gotProperty = resp.getProperties(0); + assertNotNull(gotProperty); + assertEquals(property.getTagsList(), gotProperty.getTagsList()); + }); + } + + @Test + public void test_PropertyCreateDeleteAndGet() throws BanyanDBException { + Property property = buildProperty("default", "sw", "ui_template").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("hello")))).build(); + PropertyStore store = new PropertyStore(client.getChannel()); + assertTrue(store.apply(property).getCreated()); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + BanyandbProperty.QueryResponse resp = client.query(BanyandbProperty.QueryRequest.newBuilder() + .addGroups("default") + .setName("sw") + .addIds("ui_template") + .build()); + assertEquals(1, resp.getPropertiesCount()); + Property gotProperty = resp.getProperties(0); + assertNotNull(gotProperty); + assertEquals(property.getTagsList(), gotProperty.getTagsList()); + }); + BanyandbProperty.DeleteResponse result = store.delete("default", "sw", "ui_template"); + assertTrue(result.getDeleted()); + BanyandbProperty.QueryResponse resp = client.query(BanyandbProperty.QueryRequest.newBuilder() + .addGroups("default") + .setName("sw") + .addIds("ui_template") + .build()); + assertEquals(0, resp.getPropertiesCount()); + } + + @Test + public void test_PropertyCreateUpdateAndGet() throws BanyanDBException { + Property property1 = buildProperty("default", "sw", "ui_template").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("hello")))).build(); + PropertyStore store = new PropertyStore(client.getChannel()); + assertTrue(store.apply(property1).getCreated()); + + Property property2 = buildProperty("default", "sw", "ui_template").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("word")))).build(); + assertFalse(store.apply(property2).getCreated()); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + BanyandbProperty.QueryResponse resp = client.query(BanyandbProperty.QueryRequest.newBuilder() + .addGroups("default") + .setName("sw") + .addIds("ui_template") + .build()); + assertEquals(1, resp.getPropertiesCount()); + Property gotProperty = resp.getProperties(0); + assertNotNull(gotProperty); + assertEquals(property2.getTagsList(), gotProperty.getTagsList()); + }); + } + + @Test + public void test_PropertyList() throws BanyanDBException { + Property property = buildProperty("default", "sw", "id1").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("bar")))).build(); + PropertyStore store = new PropertyStore(client.getChannel()); + assertTrue(store.apply(property).getCreated()); + property = buildProperty("default", "sw", "id2").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("foo")))).build(); + assertTrue(store.apply(property).getCreated()); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + client.query(new PropertyQuery(Lists.newArrayList("default"), "sw", ImmutableSet.of("name")).build()); + BanyandbProperty.QueryResponse resp = client.query(BanyandbProperty.QueryRequest.newBuilder() + .addGroups("default") + .setName("sw") + .build()); + assertEquals(2, resp.getPropertiesCount()); + }); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + BanyandbProperty.QueryResponse resp = client.query(BanyandbProperty.QueryRequest.newBuilder() + .addGroups("default") + .setName("sw") + .addIds("id1") + .addIds("id2") + .build()); + assertEquals(2, resp.getPropertiesCount()); + }); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + BanyandbProperty.QueryResponse resp = client.query(BanyandbProperty.QueryRequest.newBuilder() + .addGroups("default") + .setName("sw") + .addIds("id2") + .build()); + assertEquals(1, resp.getPropertiesCount()); + }); + } + + @Test + public void test_PropertyQuery() throws BanyanDBException { + Property property = buildProperty("default", "sw", "id1").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("bar")))).build(); + PropertyStore store = new PropertyStore(client.getChannel()); + assertTrue(store.apply(property).getCreated()); + property = buildProperty("default", "sw", "id2").toBuilder().addTags( + Tag.newBuilder().setKey("name").setValue( + TagValue.newBuilder().setStr(Str.newBuilder().setValue("foo")))).build(); + assertTrue(store.apply(property).getCreated()); + + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + BanyandbProperty.QueryResponse resp = client.query(new PropertyQuery(Lists.newArrayList("default"), "sw", ImmutableSet.of("name")).build()); + assertEquals(2, resp.getPropertiesCount()); + }); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + PropertyQuery pQuery = new PropertyQuery(Lists.newArrayList("default"), "sw", ImmutableSet.of("name")); + pQuery.criteria(PairQueryCondition.StringQueryCondition.eq("name", "foo")); + BanyandbProperty.QueryResponse resp = client.query(pQuery.build()); + assertEquals(1, resp.getPropertiesCount()); + }); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + PropertyQuery pQuery = new PropertyQuery(Lists.newArrayList("default"), "sw", ImmutableSet.of("name")); + pQuery.criteria(Or.create(PairQueryCondition.StringQueryCondition.eq("name", "foo"), + PairQueryCondition.StringQueryCondition.eq("name", "bar"))); + BanyandbProperty.QueryResponse resp = client.query(pQuery.build()); + assertEquals(2, resp.getPropertiesCount()); + }); + } + + private Property buildProperty(String group, String name, String id) { + Property.Builder builder = Property.newBuilder() + .setMetadata( + Metadata.newBuilder() + .setGroup( + group) + .setName( + name).build()) + .setId(id); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBStreamQueryTests.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBStreamQueryTests.java new file mode 100644 index 000000000000..bbc1688d4c7a --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITBanyanDBStreamQueryTests.java @@ -0,0 +1,260 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import io.grpc.stub.StreamObserver; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.Arrays; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Group; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Catalog; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.IntervalRule; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.ResourceOpts; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Entity; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagFamilySpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Stream; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRule; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRuleBinding; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.util.TimeUtils; +import java.io.IOException; +import java.time.Instant; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient.DEFAULT_EXPIRE_AT; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; + +public class ITBanyanDBStreamQueryTests extends BanyanDBClientTestCI { + + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + this.setUpConnection(); + this.client.define(buildGroup()); + this.client.define(buildStream()); + this.client.define(buildIndexRule()); + this.client.define(buildIndexRuleBinding()); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testStreamQuery_TraceID() throws BanyanDBException, ExecutionException, InterruptedException, TimeoutException { + // try to write a trace + String segmentId = "1231.dfd.123123ssf"; + String traceId = "trace_id-xxfff.111323"; + String serviceId = "webapp_id"; + String serviceInstanceId = "10.0.0.1_id"; + String endpointId = "home_id"; + long latency = 200; + long state = 1; + Instant now = Instant.now(); + byte[] byteData = new byte[] {14}; + String broker = "172.16.10.129:9092"; + String topic = "topic_1"; + String queue = "queue_2"; + String httpStatusCode = "200"; + String dbType = "SQL"; + String dbInstance = "127.0.0.1:3306"; + + StreamWrite streamWrite = client.createStreamWrite("sw_record", "record", segmentId) + .tag("storage-only", "data_binary", Value.binaryTagValue(byteData)) + .tag("searchable", "trace_id", Value.stringTagValue(traceId)) // 0 + .tag("searchable", "state", Value.longTagValue(state)) // 1 + .tag("searchable", "service_id", Value.stringTagValue(serviceId)) // 2 + .tag( + "searchable", "service_instance_id", + Value.stringTagValue(serviceInstanceId) + ) // 3 + .tag("searchable", "endpoint_id", Value.stringTagValue(endpointId)) // 4 + .tag("searchable", "duration", Value.longTagValue(latency)) // 5 + .tag("searchable", "http.method", Value.stringTagValue(null)) // 6 + .tag("searchable", "status_code", Value.stringTagValue(httpStatusCode)) // 7 + .tag("searchable", "db.type", Value.stringTagValue(dbType)) // 8 + .tag("searchable", "db.instance", Value.stringTagValue(dbInstance)) // 9 + .tag("searchable", "mq.broker", Value.stringTagValue(broker)) // 10 + .tag("searchable", "mq.topic", Value.stringTagValue(topic)) // 11 + .tag("searchable", "mq.queue", Value.stringTagValue(queue)); // 12 + streamWrite.setTimestamp(now.toEpochMilli()); + StreamObserver writeObserver + = client.getStreamServiceStub().write(new StreamObserver() { + @Override + public void onNext(BanyandbStream.WriteResponse writeResponse) { + assertEquals(BanyandbModel.Status.STATUS_SUCCEED.name(), writeResponse.getStatus()); + } + + @Override + public void onError(Throwable throwable) { + fail("write failed: " + throwable.getMessage()); + } + + @Override + public void onCompleted() { + } + }); + try { + writeObserver.onNext(streamWrite.build()); + + } finally { + writeObserver.onCompleted(); + } + + StreamQuery query = new StreamQuery( + Lists.newArrayList("sw_record"), "record", + ImmutableMap.of( + "state", "searchable", "duration", "searchable", "trace_id", "searchable", "data_binary", + "storage-only" + ) + ); + query.and(PairQueryCondition.StringQueryCondition.eq("trace_id", traceId)); + query.setOrderBy(new AbstractQuery.OrderBy(AbstractQuery.Sort.DESC)); + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + StreamQueryResponse resp = client.query(query); + assertNotNull(resp); + assertEquals(1, resp.size()); + assertEquals(latency, (Number) resp.getElements().get(0).getTagValue("duration")); + assertEquals(traceId, resp.getElements().get(0).getTagValue("trace_id")); + }); + } + + private Group buildGroup() { + return Group.newBuilder().setMetadata(Metadata.newBuilder().setName("sw_record")) + .setCatalog(Catalog.CATALOG_STREAM) + .setResourceOpts(ResourceOpts.newBuilder() + .setShardNum(2) + .setSegmentInterval( + IntervalRule.newBuilder() + .setUnit( + IntervalRule.Unit.UNIT_DAY) + .setNum( + 1)) + .setTtl( + IntervalRule.newBuilder() + .setUnit( + IntervalRule.Unit.UNIT_DAY) + .setNum( + 3))) + .build(); + } + + private Stream buildStream() { + Stream.Builder builder = Stream.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_record") + .setName("record")) + .setEntity(Entity.newBuilder().addAllTagNames( + Arrays.asList("service_id", "service_instance_id", "state"))) + .addTagFamilies(TagFamilySpec.newBuilder() + .setName("data") + .addTags(TagSpec.newBuilder() + .setName("data_binary") + .setType( + TagType.TAG_TYPE_DATA_BINARY))) + .addTagFamilies(TagFamilySpec.newBuilder() + .setName("searchable") + .addTags(TagSpec.newBuilder() + .setName("trace_id") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("state") + .setType(TagType.TAG_TYPE_INT)) + .addTags(TagSpec.newBuilder() + .setName("service_id") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("service_instance_id") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("endpoint_id") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("duration") + .setType(TagType.TAG_TYPE_INT)) + .addTags(TagSpec.newBuilder() + .setName("http.method") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("status_code") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("db.type") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("db.instance") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("mq.broker") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("mq.topic") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("mq.queue") + .setType(TagType.TAG_TYPE_STRING))); + return builder.build(); + } + + private IndexRule buildIndexRule() { + IndexRule.Builder builder = IndexRule.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_record") + .setName("trace_id")) + .addTags("trace_id") + .setType(IndexRule.Type.TYPE_INVERTED); + return builder.build(); + } + + private IndexRuleBinding buildIndexRuleBinding() { + IndexRuleBinding.Builder builder = IndexRuleBinding.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_record") + .setName("trace_binding")) + .setSubject(BanyandbDatabase.Subject.newBuilder() + .setCatalog( + Catalog.CATALOG_STREAM) + .setName("trace")) + .addAllRules( + Arrays.asList("trace_id")) + .setBeginAt(TimeUtils.buildTimestamp( + ZonedDateTime.of( + 2024, 1, 1, 0, 0, 0, 0, + ZoneOffset.UTC + ))) + .setExpireAt(TimeUtils.buildTimestamp(DEFAULT_EXPIRE_AT)); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITGroupMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITGroupMetadataRegistryTest.java new file mode 100644 index 000000000000..3b3155f77448 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITGroupMetadataRegistryTest.java @@ -0,0 +1,203 @@ +/* + * 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.library.banyandb.v1.client; + +import java.io.IOException; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Group; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Catalog; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.IntervalRule; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.ResourceOpts; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.LifecycleStage; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ITGroupMetadataRegistryTest extends BanyanDBClientTestCI { + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testGroupRegistry_createAndGet() throws BanyanDBException { + Group expectedGroup = buildGroup(); + this.client.define(expectedGroup); + Group actualGroup = client.findGroup("sw_metric"); + assertNotNull(actualGroup); + assertNotNull(actualGroup.getUpdatedAt()); + actualGroup = actualGroup.toBuilder().setMetadata(actualGroup.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedGroup, actualGroup); + } + + @Test + public void testGroupRegistry_createAndUpdate() throws BanyanDBException { + this.client.define(buildGroup()); + Group beforeGroup = client.findGroup("sw_metric"); + assertNotNull(beforeGroup); + assertNotNull(beforeGroup.getUpdatedAt()); + Group updatedGroup = beforeGroup.toBuilder() + .setResourceOpts(beforeGroup.getResourceOpts() + .toBuilder() + .setTtl(IntervalRule.newBuilder() + .setUnit( + IntervalRule.Unit.UNIT_DAY) + .setNum(3))) + .build(); + this.client.update(updatedGroup); + Group afterGroup = client.findGroup("sw_metric"); + updatedGroup = updatedGroup.toBuilder().setMetadata(updatedGroup.getMetadata().toBuilder().clearModRevision()).build(); + afterGroup = afterGroup.toBuilder().setMetadata(afterGroup.getMetadata().toBuilder().clearModRevision()).build(); + assertNotNull(afterGroup); + assertNotNull(afterGroup.getUpdatedAt()); + assertEquals(updatedGroup, afterGroup); + } + + @Test + public void testGroupRegistry_createAndList() throws BanyanDBException { + Group expectedGroup = buildGroup(); + this.client.define(buildGroup()); + List actualGroups = client.findGroups(); + assertNotNull(actualGroups); + assertEquals(1, actualGroups.size()); + Group actualGroup = actualGroups.get(0); + actualGroup = actualGroup.toBuilder().setMetadata(actualGroup.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedGroup, actualGroup); + } + + @Test + public void testGroupRegistry_createAndDelete() throws BanyanDBException { + this.client.define(buildGroup()); + boolean deleted = this.client.deleteGroup("sw_metric"); + assertTrue(deleted); + assertNull(client.findGroup("sw_metric")); + } + + @Test + public void testGroupRegistry_hotWarmCold() throws BanyanDBException { + Group g = Group.newBuilder().setMetadata(Metadata.newBuilder().setName("sw_record")) + .setCatalog(Catalog.CATALOG_STREAM) + .setResourceOpts(ResourceOpts.newBuilder() + .setShardNum(3) + .setSegmentInterval( + IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(1)) + .setTtl( + IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(3)) + .addStages(LifecycleStage.newBuilder() + .setName("warm") + .setShardNum(2) + .setSegmentInterval(IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(1)) + .setTtl(IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(7)) + .setNodeSelector("hdd-nodes") + .build()) + .addStages(LifecycleStage.newBuilder() + .setName("cold") + .setShardNum(1) + .setSegmentInterval(IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(7)) + .setTtl(IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(30)) + .setNodeSelector("archive-nodes") + .setClose(true) + .build())) + .build(); + this.client.define(g); + Group actualGroup = client.findGroup("sw_record"); + assertNotNull(actualGroup); + assertNotNull(actualGroup.getUpdatedAt()); + + // Verify group exists + assertNotNull(actualGroup); + + // Verify basic metadata + assertEquals("sw_record", actualGroup.getMetadata().getName()); + assertEquals(Catalog.CATALOG_STREAM, actualGroup.getCatalog()); + + // Verify resource options + ResourceOpts actualOpts = actualGroup.getResourceOpts(); + assertEquals(3, actualOpts.getShardNum()); + assertEquals(IntervalRule.Unit.UNIT_DAY, actualOpts.getSegmentInterval().getUnit()); + assertEquals(1, actualOpts.getSegmentInterval().getNum()); + assertEquals(IntervalRule.Unit.UNIT_DAY, actualOpts.getTtl().getUnit()); + assertEquals(3, actualOpts.getTtl().getNum()); + + // Verify stages (should have 2 stages: warm and cold) + assertEquals(2, actualOpts.getStagesCount()); + + // Verify warm stage + LifecycleStage warmStage = actualOpts.getStages(0); + assertEquals("warm", warmStage.getName()); + assertEquals(2, warmStage.getShardNum()); + assertEquals(1, warmStage.getSegmentInterval().getNum()); + assertEquals(IntervalRule.Unit.UNIT_DAY, warmStage.getSegmentInterval().getUnit()); + assertEquals(7, warmStage.getTtl().getNum()); + assertEquals("hdd-nodes", warmStage.getNodeSelector()); + + // Verify cold stage + LifecycleStage coldStage = actualOpts.getStages(1); + assertEquals("cold", coldStage.getName()); + assertEquals(1, coldStage.getShardNum()); + assertEquals(7, coldStage.getSegmentInterval().getNum()); + assertEquals(30, coldStage.getTtl().getNum()); + assertEquals("archive-nodes", coldStage.getNodeSelector()); + assertTrue(coldStage.getClose()); + } + + private Group buildGroup() { + return Group.newBuilder().setMetadata(Metadata.newBuilder().setName("sw_metric")) + .setCatalog(Catalog.CATALOG_MEASURE) + .setResourceOpts(ResourceOpts.newBuilder() + .setShardNum(2) + .setSegmentInterval( + IntervalRule.newBuilder() + .setUnit( + IntervalRule.Unit.UNIT_DAY) + .setNum( + 1)) + .setTtl( + IntervalRule.newBuilder() + .setUnit( + IntervalRule.Unit.UNIT_DAY) + .setNum( + 7))) + .build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITIndexRuleBindingMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITIndexRuleBindingMetadataRegistryTest.java new file mode 100644 index 000000000000..cddd767ada2f --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITIndexRuleBindingMetadataRegistryTest.java @@ -0,0 +1,119 @@ +/* + * 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.library.banyandb.v1.client; + +import java.io.IOException; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRuleBinding; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.IndexRuleBindingMetadataRegistry; +import org.apache.skywalking.library.banyandb.v1.client.util.TimeUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient.DEFAULT_EXPIRE_AT; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ITIndexRuleBindingMetadataRegistryTest extends BanyanDBClientTestCI { + private IndexRuleBindingMetadataRegistry registry; + + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + BanyandbCommon.Group expectedGroup = buildStreamGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testIndexRuleBindingRegistry_createAndGet() throws BanyanDBException { + IndexRuleBinding indexRuleBinding = buildIndexRuleBinding(); + this.client.define(indexRuleBinding); + IndexRuleBinding getIndexRuleBinding = this.client.findIndexRuleBinding("sw_record", "trace_binding"); + assertNotNull(getIndexRuleBinding); + getIndexRuleBinding = getIndexRuleBinding.toBuilder() + .clearUpdatedAt() + .setMetadata(getIndexRuleBinding.getMetadata() + .toBuilder() + .clearModRevision() + .clearCreateRevision()) + .build(); + assertEquals(indexRuleBinding, getIndexRuleBinding); + assertNotNull(getIndexRuleBinding.getUpdatedAt()); + } + + @Test + public void testIndexRuleBindingRegistry_createAndList() throws BanyanDBException { + IndexRuleBinding indexRuleBinding = buildIndexRuleBinding(); + this.client.define(indexRuleBinding); + List listIndexRuleBinding = this.client.findIndexRuleBindings("sw_record"); + assertNotNull(listIndexRuleBinding); + IndexRuleBinding actualIndexRuleBinding = listIndexRuleBinding.get(0); + actualIndexRuleBinding = actualIndexRuleBinding.toBuilder() + .clearUpdatedAt() + .setMetadata(actualIndexRuleBinding.getMetadata() + .toBuilder() + .clearModRevision() + .clearCreateRevision()) + .build(); + assertEquals(1, listIndexRuleBinding.size()); + assertEquals(actualIndexRuleBinding, indexRuleBinding); + } + + @Test + public void testIndexRuleBindingRegistry_createAndDelete() throws BanyanDBException { + IndexRuleBinding indexRuleBinding = buildIndexRuleBinding(); + this.client.define(indexRuleBinding); + boolean deleted = this.client.deleteIndexRuleBinding("sw_record", "trace_binding"); + assertTrue(deleted); + assertNull(client.findIndexRuleBinding(indexRuleBinding.getMetadata().getGroup(), + indexRuleBinding.getMetadata().getName() + )); + } + + private IndexRuleBinding buildIndexRuleBinding() { + IndexRuleBinding.Builder builder = IndexRuleBinding.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder() + .setGroup("sw_record") + .setName("trace_binding")) + .setSubject(BanyandbDatabase.Subject.newBuilder() + .setCatalog( + BanyandbCommon.Catalog.CATALOG_STREAM) + .setName("trace")) + .addAllRules( + Arrays.asList("trace_id")) + .setBeginAt(TimeUtils.buildTimestamp(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC))) + .setExpireAt(TimeUtils.buildTimestamp(DEFAULT_EXPIRE_AT)); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITIndexRuleMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITIndexRuleMetadataRegistryTest.java new file mode 100644 index 000000000000..53ff7dd9cf30 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITIndexRuleMetadataRegistryTest.java @@ -0,0 +1,121 @@ +/* + * 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.library.banyandb.v1.client; + +import java.io.IOException; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRule; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.IndexRuleMetadataRegistry; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ITIndexRuleMetadataRegistryTest extends BanyanDBClientTestCI { + private IndexRuleMetadataRegistry registry; + + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + BanyandbCommon.Group expectedGroup = buildStreamGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testIndexRuleRegistry_createAndGet() throws BanyanDBException { + IndexRule indexRule = buildIndexRule(); + this.client.define(indexRule); + IndexRule getIndexRule = this.client.findIndexRule("sw_record", "trace_id"); + assertNotNull(getIndexRule); + getIndexRule = getIndexRule.toBuilder() + .clearUpdatedAt() + .setMetadata(getIndexRule.getMetadata() + .toBuilder() + .clearCreateRevision() + .clearModRevision() + .clearId()) + .build(); + assertEquals(indexRule, getIndexRule); + assertNotNull(getIndexRule.getUpdatedAt()); + } + + @Test + public void testIndexRuleRegistry_createAndList() throws BanyanDBException { + IndexRule indexRule = buildIndexRule(); + this.client.define(indexRule); + List listIndexRule = this.client.findIndexRules("sw_record"); + assertNotNull(listIndexRule); + assertEquals(1, listIndexRule.size()); + IndexRule actualIndexRule = listIndexRule.get(0); + actualIndexRule = actualIndexRule.toBuilder() + .clearUpdatedAt() + .setMetadata(actualIndexRule.getMetadata() + .toBuilder() + .clearCreateRevision() + .clearModRevision() + .clearId()) + .build(); + assertEquals(actualIndexRule, indexRule); + } + + @Test + public void testIndexRuleRegistry_createAndUpdate() throws BanyanDBException { + this.client.define(buildIndexRule()); + IndexRule before = client.findIndexRule("sw_record", "trace_id"); + assertEquals("simple", before.getAnalyzer()); + IndexRule updatedIndexRule = before.toBuilder().setAnalyzer("standard").build(); + this.client.update(updatedIndexRule); + IndexRule after = this.client.findIndexRule("sw_record", "trace_id"); + assertNotNull(after); + assertEquals("standard", after.getAnalyzer()); + } + + @Test + public void testIndexRuleRegistry_createAndDelete() throws BanyanDBException { + IndexRule indexRule = buildIndexRule(); + client.define(indexRule); + boolean deleted = this.client.deleteIndexRule("sw_record", "trace_id"); + assertTrue(deleted); + assertNull(client.findIndexRule(indexRule.getMetadata().getGroup(), indexRule.getMetadata().getName())); + } + + private IndexRule buildIndexRule() { + IndexRule.Builder builder = IndexRule.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_record") + .setName("trace_id")) + .addTags("trace_id") + .setType(IndexRule.Type.TYPE_INVERTED) + .setAnalyzer("simple"); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITMeasureMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITMeasureMetadataRegistryTest.java new file mode 100644 index 000000000000..3c376e75eee4 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITMeasureMetadataRegistryTest.java @@ -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. + * + */ + +package org.apache.skywalking.library.banyandb.v1.client; + +import java.io.IOException; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.CompressionMethod; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.EncodingMethod; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Entity; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.FieldSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.FieldType; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Measure; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.ShardingKey; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagFamilySpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Duration; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +public class ITMeasureMetadataRegistryTest extends BanyanDBClientTestCI { + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + BanyandbCommon.Group expectedGroup = buildMeasureGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testMeasureRegistry_createAndGet() throws BanyanDBException { + Measure expectedMeasure = buildMeasure(); + this.client.define(expectedMeasure); + Measure actualMeasure = client.findMeasure("sw_metric", "service_cpm_minute"); + assertNotNull(actualMeasure); + assertNotNull(actualMeasure.getUpdatedAt()); + actualMeasure = actualMeasure.toBuilder().clearUpdatedAt().setMetadata(actualMeasure.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedMeasure, actualMeasure); + } + + @Test + public void testMeasureRegistry_createAndList() throws BanyanDBException { + Measure expectedMeasure = buildMeasure(); + this.client.define(expectedMeasure); + List actualMeasures = client.findMeasures("sw_metric"); + assertNotNull(actualMeasures); + // _topn_result is a system measure, so there should be 2 measures + assertTrue(actualMeasures.size() > 0); + boolean found = false; + for (Measure actualMeasure : actualMeasures) { + if (actualMeasure.getMetadata().getName().equals("service_cpm_minute")) { + found = true; + actualMeasure = actualMeasure.toBuilder().clearUpdatedAt().setMetadata(actualMeasure.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedMeasure, actualMeasure); + } + } + if (!found) { + fail("service_cpm_minute not found"); + } + } + + @Test + public void testMeasureRegistry_createAndDelete() throws BanyanDBException { + Measure expectedMeasure = buildMeasure(); + this.client.define(expectedMeasure); + boolean deleted = this.client.deleteMeasure( + expectedMeasure.getMetadata().getGroup(), expectedMeasure.getMetadata().getName()); + assertTrue(deleted); + assertNull( + client.findMeasure(expectedMeasure.getMetadata().getGroup(), expectedMeasure.getMetadata().getName())); + } + + private Measure buildMeasure() { + Measure.Builder builder = Measure.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_metric") + .setName("service_cpm_minute")) + .setInterval(Duration.ofMinutes(1).format()) + .setEntity(Entity.newBuilder().addTagNames("entity_id")) + .setShardingKey(ShardingKey.newBuilder().addTagNames("service_id")) + .addTagFamilies( + TagFamilySpec.newBuilder() + .setName("default") + .addTags( + TagSpec.newBuilder() + .setName("entity_id") + .setType( + TagType.TAG_TYPE_STRING)) + .addTags( + TagSpec.newBuilder() + .setName("scope") + .setType( + TagType.TAG_TYPE_STRING))) + .addFields( + FieldSpec.newBuilder() + .setName("total") + .setFieldType( + FieldType.FIELD_TYPE_INT) + .setCompressionMethod( + CompressionMethod.COMPRESSION_METHOD_ZSTD) + .setEncodingMethod( + EncodingMethod.ENCODING_METHOD_GORILLA)) + .addFields( + FieldSpec.newBuilder() + .setName("value") + .setFieldType( + FieldType.FIELD_TYPE_INT) + .setCompressionMethod( + CompressionMethod.COMPRESSION_METHOD_ZSTD) + .setEncodingMethod( + EncodingMethod.ENCODING_METHOD_GORILLA)); + return builder.build(); + } + + @Test + public void testIndexMeasureRegistry_createAndGet() throws BanyanDBException { + Measure expectedMeasure = buildIndexMeasure(); + this.client.define(expectedMeasure); + Measure actualMeasure = client.findMeasure("sw_metric", "service_traffic"); + assertNotNull(actualMeasure); + assertNotNull(actualMeasure.getUpdatedAt()); + actualMeasure = actualMeasure.toBuilder().clearUpdatedAt().setMetadata(actualMeasure.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedMeasure, actualMeasure); + } + + private Measure buildIndexMeasure() { + Measure.Builder builder = Measure.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_metric") + .setName("service_traffic")) + .setEntity(Entity.newBuilder().addTagNames("id")) + .setIndexMode(true) + .addTagFamilies( + TagFamilySpec.newBuilder() + .setName("default") + .addTags( + TagSpec.newBuilder() + .setName("id") + .setType( + TagType.TAG_TYPE_STRING)) + .addTags( + TagSpec.newBuilder() + .setName("service_name") + .setType( + TagType.TAG_TYPE_STRING))); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITPropertyMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITPropertyMetadataRegistryTest.java new file mode 100644 index 000000000000..6a6526b74f64 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITPropertyMetadataRegistryTest.java @@ -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.library.banyandb.v1.client; + +import java.io.IOException; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Property; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.NotFoundException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ITPropertyMetadataRegistryTest extends BanyanDBClientTestCI { + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + BanyandbCommon.Group expectedGroup = buildPropertyGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testPropertyRegistry_createAndGet() throws BanyanDBException { + Property expectedProperty = buildProperty(); + this.client.define(expectedProperty); + Property actualProperty = client.findPropertyDefinition("sw_config", "ui_template"); + assertNotNull(actualProperty); + assertNotNull(actualProperty.getUpdatedAt()); + actualProperty = actualProperty.toBuilder().clearUpdatedAt().setMetadata(actualProperty.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedProperty, actualProperty); + } + + @Test + public void testPropertyRegistry_createAndList() throws BanyanDBException { + Property expectedProperty = buildProperty(); + this.client.define(expectedProperty); + List actualProperties = client.findPropertiesDefinition("sw_config"); + assertNotNull(actualProperties); + assertEquals(1, actualProperties.size()); + Property actualProperty = actualProperties.get(0); + actualProperty = actualProperty.toBuilder().clearUpdatedAt().setMetadata(actualProperty.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedProperty, actualProperty); + } + + @Test + public void testPropertyRegistry_createAndDelete() throws BanyanDBException { + Property expectedProperty = buildProperty(); + this.client.define(expectedProperty); + boolean deleted = this.client.deletePropertyDefinition( + expectedProperty.getMetadata().getGroup(), expectedProperty.getMetadata().getName()); + assertTrue(deleted); + assertThrows( + NotFoundException.class, + () -> client.findPropertyDefinition( + expectedProperty.getMetadata().getGroup(), expectedProperty.getMetadata().getName()) + ); + } + + private Property buildProperty() { + Property.Builder builder = Property.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_config") + .setName("ui_template")) + .addTags( + TagSpec.newBuilder() + .setName("type") + .setType( + TagType.TAG_TYPE_STRING)) + .addTags( + TagSpec.newBuilder() + .setName("service") + .setType( + TagType.TAG_TYPE_STRING)); + return builder.build(); + } + + private BanyandbCommon.Group buildPropertyGroup() { + return BanyandbCommon.Group.newBuilder() + .setMetadata(Metadata.newBuilder() + .setName("sw_config") + .build()) + .setCatalog(BanyandbCommon.Catalog.CATALOG_PROPERTY) + .setResourceOpts(BanyandbCommon.ResourceOpts.newBuilder() + .setShardNum(2)) + .build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITStreamMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITStreamMetadataRegistryTest.java new file mode 100644 index 000000000000..737b9f22488e --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITStreamMetadataRegistryTest.java @@ -0,0 +1,132 @@ +/* + * 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.library.banyandb.v1.client; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Entity; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Stream; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagFamilySpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ITStreamMetadataRegistryTest extends BanyanDBClientTestCI { + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + BanyandbCommon.Group expectedGroup = buildStreamGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testStreamRegistry_createAndGet() throws BanyanDBException { + Stream expectedStream = buildStream(); + this.client.define(expectedStream); + Stream actualStream = client.findStream("sw_record", "record"); + assertNotNull(actualStream); + assertNotNull(actualStream.getUpdatedAt()); + actualStream = actualStream.toBuilder().clearUpdatedAt().setMetadata(actualStream.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedStream, actualStream); + } + + @Test + public void testStreamRegistry_createAndUpdate() throws BanyanDBException { + Stream expectedStream = buildStream(); + this.client.define(expectedStream); + Stream beforeStream = client.findStream("sw_record", "record"); + assertNotNull(beforeStream); + assertNotNull(beforeStream.getUpdatedAt()); + Stream updatedStream = beforeStream.toBuilder().addTagFamilies(TagFamilySpec.newBuilder() + .setName("ex") + .addTags(TagSpec.newBuilder() + .setName("ex") + .setType(TagType.TAG_TYPE_INT))).build(); + this.client.update(updatedStream); + Stream afterStream = client.findStream("sw_record", "record"); + assertNotNull(afterStream); + assertNotNull(afterStream.getUpdatedAt()); + assertNotEquals(beforeStream, afterStream); + } + + @Test + public void testStreamRegistry_createAndList() throws BanyanDBException { + Stream expectedStream = buildStream(); + client.define(expectedStream); + List actualStreams = client.findStreams("sw_record"); + assertNotNull(actualStreams); + assertEquals(1, actualStreams.size()); + Stream actualStream = actualStreams.get(0); + actualStream = actualStream.toBuilder().clearUpdatedAt().setMetadata(actualStream.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedStream, actualStream); + } + + @Test + public void testStreamRegistry_createAndDelete() throws BanyanDBException { + Stream expectedStream = buildStream(); + this.client.define(expectedStream); + boolean deleted = this.client.deleteStream(expectedStream.getMetadata().getGroup(), expectedStream.getMetadata().getName()); + assertTrue(deleted); + assertNull(client.findMeasure(expectedStream.getMetadata().getGroup(), expectedStream.getMetadata().getName())); + } + + private Stream buildStream() { + Stream.Builder builder = Stream.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_record") + .setName("record")) + .setEntity(Entity.newBuilder().addAllTagNames( + Arrays.asList("service_id", "service_instance_id", "is_error"))) + .addTagFamilies(TagFamilySpec.newBuilder() + .setName("data") + .addTags(TagSpec.newBuilder() + .setName("data_binary") + .setType(TagType.TAG_TYPE_DATA_BINARY))) + .addTagFamilies(TagFamilySpec.newBuilder() + .setName("searchable") + .addTags(TagSpec.newBuilder() + .setName("trace_id") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TagSpec.newBuilder() + .setName("is_error") + .setType(TagType.TAG_TYPE_INT)) + .addTags(TagSpec.newBuilder() + .setName("service_id") + .setType(TagType.TAG_TYPE_STRING))); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTopNAggregationMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTopNAggregationMetadataRegistryTest.java new file mode 100644 index 000000000000..4de83e99108c --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTopNAggregationMetadataRegistryTest.java @@ -0,0 +1,115 @@ +/* + * 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.library.banyandb.v1.client; + +import java.io.IOException; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TopNAggregation; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ITTopNAggregationMetadataRegistryTest extends BanyanDBClientTestCI { + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + BanyandbCommon.Group expectedGroup = buildMeasureGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testTopNAggregationRegistry_createAndGet() throws BanyanDBException { + TopNAggregation expectedTopNAggregation = bindTopNAggregation(); + this.client.define(expectedTopNAggregation); + TopNAggregation actualTopNAggregation = client.findTopNAggregation("sw_metric", "service_cpm_minute_topn"); + assertNotNull(actualTopNAggregation); + assertNotNull(actualTopNAggregation.getUpdatedAt()); + actualTopNAggregation = actualTopNAggregation.toBuilder().clearUpdatedAt().setMetadata(actualTopNAggregation.getMetadata().toBuilder().clearModRevision().clearCreateRevision()).build(); + assertEquals(expectedTopNAggregation, actualTopNAggregation); + } + + @Test + public void testTopNAggregationRegistry_createAndUpdate() throws BanyanDBException { + TopNAggregation expectedTopNAggregation = bindTopNAggregation(); + this.client.define(expectedTopNAggregation); + TopNAggregation before = client.findTopNAggregation("sw_metric", "service_cpm_minute_topn"); + assertNotNull(before); + assertNotNull(before.getUpdatedAt()); + TopNAggregation updated = before.toBuilder().setFieldValueSort(BanyandbModel.Sort.SORT_ASC).build(); + this.client.update(updated); + TopNAggregation after = client.findTopNAggregation("sw_metric", "service_cpm_minute_topn"); + assertNotNull(after); + assertNotNull(after.getUpdatedAt()); + assertNotEquals(before, after); + assertEquals(BanyandbModel.Sort.SORT_ASC, after.getFieldValueSort()); + } + + @Test + public void testTopNAggregationRegistry_createAndList() throws BanyanDBException { + TopNAggregation expectedTopNAggregation = bindTopNAggregation(); + this.client.define(expectedTopNAggregation); + List actualTopNAggregations = client.findTopNAggregations("sw_metric"); + assertNotNull(actualTopNAggregations); + assertEquals(1, actualTopNAggregations.size()); + } + + @Test + public void testTopNAggregationRegistry_createAndDelete() throws BanyanDBException { + TopNAggregation expectedTopNAggregation = bindTopNAggregation(); + this.client.define(expectedTopNAggregation); + boolean deleted = this.client.deleteTopNAggregation( + expectedTopNAggregation.getMetadata().getGroup(), expectedTopNAggregation.getMetadata().getName()); + assertTrue(deleted); + assertNull(client.findMeasure(expectedTopNAggregation.getMetadata().getGroup(), + expectedTopNAggregation.getMetadata().getName() + )); + } + + private TopNAggregation bindTopNAggregation() { + TopNAggregation.Builder builder = TopNAggregation.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup("sw_metric") + .setName("service_cpm_minute_topn")) + .setFieldValueSort(BanyandbModel.Sort.SORT_DESC) + .setFieldName("value") + .setSourceMeasure(Metadata.newBuilder() + .setGroup("sw_metric") + .setName("service_cpm_minute")) + .setLruSize(10) + .setCountersNumber(1000) + .addGroupByTagNames("service_id"); + return builder.build(); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTraceMetadataRegistryTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTraceMetadataRegistryTest.java new file mode 100644 index 000000000000..6f5948703da2 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTraceMetadataRegistryTest.java @@ -0,0 +1,194 @@ +/* + * 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.library.banyandb.v1.client; + +import java.io.IOException; +import java.util.List; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Metadata; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.Catalog; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.IntervalRule; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon.ResourceOpts; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.Trace; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TraceTagSpec; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.ResourceExist; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class ITTraceMetadataRegistryTest extends BanyanDBClientTestCI { + private final String groupName = "sw_trace_registry"; + private final String traceName = "trace_registry_test"; + + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + super.setUpConnection(); + BanyandbCommon.Group expectedGroup = buildTraceGroup(); + client.define(expectedGroup); + assertNotNull(expectedGroup); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testTraceRegistry_createAndGet() throws BanyanDBException { + Trace expectedTrace = buildTrace(); + this.client.define(expectedTrace); + Trace actualTrace = client.findTrace(groupName, traceName); + assertNotNull(actualTrace); + assertNotNull(actualTrace.getUpdatedAt()); + + // Clear timestamps and revision fields for comparison + actualTrace = actualTrace.toBuilder() + .clearUpdatedAt() + .setMetadata(actualTrace.getMetadata().toBuilder() + .clearModRevision() + .clearCreateRevision()) + .build(); + assertEquals(expectedTrace, actualTrace); + } + + @Test + public void testTraceRegistry_createAndUpdate() throws BanyanDBException { + Trace expectedTrace = buildTrace(); + this.client.define(expectedTrace); + Trace beforeTrace = client.findTrace(groupName, traceName); + assertNotNull(beforeTrace); + assertNotNull(beforeTrace.getUpdatedAt()); + + // Add an additional tag + Trace updatedTrace = beforeTrace.toBuilder() + .addTags(TraceTagSpec.newBuilder() + .setName("duration") + .setType(TagType.TAG_TYPE_INT)) + .build(); + + this.client.update(updatedTrace); + Trace afterTrace = client.findTrace(groupName, traceName); + assertNotNull(afterTrace); + assertNotNull(afterTrace.getUpdatedAt()); + assertNotEquals(beforeTrace, afterTrace); + assertEquals(beforeTrace.getTagsCount() + 1, afterTrace.getTagsCount()); + } + + @Test + public void testTraceRegistry_list() throws BanyanDBException { + Trace expectedTrace = buildTrace(); + this.client.define(expectedTrace); + + List traces = client.findTraces(groupName); + assertNotNull(traces); + assertTrue(traces.size() >= 1); + + boolean found = false; + for (Trace trace : traces) { + if (traceName.equals(trace.getMetadata().getName())) { + found = true; + break; + } + } + assertTrue(found); + } + + @Test + public void testTraceRegistry_exist() throws BanyanDBException { + Trace expectedTrace = buildTrace(); + this.client.define(expectedTrace); + + ResourceExist exist = client.existTrace(groupName, traceName); + assertNotNull(exist); + assertTrue(exist.isHasGroup()); + assertTrue(exist.isHasResource()); + + // Test non-existent trace + ResourceExist nonExist = client.existTrace(groupName, "non-existent-trace"); + assertNotNull(nonExist); + assertTrue(nonExist.isHasGroup()); + assertFalse(nonExist.isHasResource()); + } + + @Test + public void testTraceRegistry_delete() throws BanyanDBException { + Trace expectedTrace = buildTrace(); + this.client.define(expectedTrace); + + // Verify it exists + assertNotNull(client.findTrace(groupName, traceName)); + + // Delete it + boolean deleted = client.deleteTrace(groupName, traceName); + assertTrue(deleted); + + // Verify it no longer exists + assertNull(client.findTrace(groupName, traceName)); + } + + private BanyandbCommon.Group buildTraceGroup() { + return BanyandbCommon.Group.newBuilder() + .setMetadata(Metadata.newBuilder().setName(groupName)) + .setCatalog(Catalog.CATALOG_TRACE) + .setResourceOpts(ResourceOpts.newBuilder() + .setShardNum(2) + .setSegmentInterval(IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(1)) + .setTtl(IntervalRule.newBuilder() + .setUnit(IntervalRule.Unit.UNIT_DAY) + .setNum(7))) + .build(); + } + + private Trace buildTrace() { + return Trace.newBuilder() + .setMetadata(Metadata.newBuilder() + .setGroup(groupName) + .setName(traceName)) + .addTags(TraceTagSpec.newBuilder() + .setName("trace_id") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TraceTagSpec.newBuilder() + .setName("span_id") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TraceTagSpec.newBuilder() + .setName("service_name") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TraceTagSpec.newBuilder() + .setName("operation_name") + .setType(TagType.TAG_TYPE_STRING)) + .addTags(TraceTagSpec.newBuilder() + .setName("start_time") + .setType(TagType.TAG_TYPE_TIMESTAMP)) + .setTraceIdTagName("trace_id") + .setSpanIdTagName("spanId") + .setTimestampTagName("start_time") + .build(); + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTraceTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTraceTest.java new file mode 100644 index 000000000000..111b2873ed29 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/ITTraceTest.java @@ -0,0 +1,331 @@ +/* + * 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.library.banyandb.v1.client; + +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Lists; +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.model.v1.BanyandbModel; +import org.apache.skywalking.banyandb.trace.v1.BanyandbTrace; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.util.TimeUtils; +import java.io.IOException; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient.DEFAULT_EXPIRE_AT; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.testcontainers.shaded.org.awaitility.Awaitility.await; + +/** + * Integration test for trace functionality. + * Note: This test demonstrates the trace API but requires a running BanyanDB instance. + */ +public class ITTraceTest extends BanyanDBClientTestCI { + private final String groupName = "sw_trace"; + private final String traceName = "trace_data"; + + @BeforeEach + public void setUp() throws IOException, BanyanDBException, InterruptedException { + this.setUpConnection(); + // Create trace group + BanyandbCommon.Group traceGroup = BanyandbCommon.Group.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder() + .setName(groupName)) + .setCatalog(BanyandbCommon.Catalog.CATALOG_TRACE) + .setResourceOpts(BanyandbCommon.ResourceOpts.newBuilder() + .setShardNum( + 2) + .setSegmentInterval( + BanyandbCommon.IntervalRule.newBuilder() + .setUnit( + BanyandbCommon.IntervalRule.Unit.UNIT_DAY) + .setNum( + 1)) + .setTtl( + BanyandbCommon.IntervalRule.newBuilder() + .setUnit( + BanyandbCommon.IntervalRule.Unit.UNIT_DAY) + .setNum( + 7))) + .build(); + + this.client.define(traceGroup); + + // Create trace schema + BanyandbDatabase.Trace trace = BanyandbDatabase.Trace.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder() + .setGroup(groupName) + .setName(traceName)) + .addTags(BanyandbDatabase.TraceTagSpec.newBuilder() + .setName("trace_id") + .setType( + BanyandbDatabase.TagType.TAG_TYPE_STRING)) + .addTags(BanyandbDatabase.TraceTagSpec.newBuilder() + .setName("span_id") + .setType( + BanyandbDatabase.TagType.TAG_TYPE_STRING)) + .addTags(BanyandbDatabase.TraceTagSpec.newBuilder() + .setName( + "service_name") + .setType( + BanyandbDatabase.TagType.TAG_TYPE_STRING)) + .addTags(BanyandbDatabase.TraceTagSpec.newBuilder() + .setName( + "start_time") + .setType( + BanyandbDatabase.TagType.TAG_TYPE_TIMESTAMP)) + .setTraceIdTagName("trace_id") + .setSpanIdTagName("span_id") + .setTimestampTagName("start_time") + .build(); + + this.client.define(trace); + this.client.define(buildIndexRule()); + this.client.define(buildIndexRuleBinding()); + } + + @AfterEach + public void tearDown() throws IOException { + this.closeClient(); + } + + @Test + public void testTraceSchemaOperations() throws BanyanDBException { + // Test trace definition exists + BanyandbDatabase.Trace retrievedTrace = client.findTrace(groupName, traceName); + assertNotNull(retrievedTrace); + assertEquals(traceName, retrievedTrace.getMetadata().getName()); + assertEquals(groupName, retrievedTrace.getMetadata().getGroup()); + + // Test trace exists + assertTrue(client.existTrace(groupName, traceName).isHasResource()); + } + + @Test + public void testTraceQueryByTraceId() throws BanyanDBException, ExecutionException, InterruptedException, TimeoutException { + // Test data + String traceId = "trace-query-test-12345"; + String spanId = "span-query-test-67890"; + String serviceName = "query-test-service"; + Instant now = Instant.now(); + byte[] spanData = "query-test-span-data".getBytes(); + + // Create and write trace data + TraceWrite traceWrite = client.createTraceWrite(groupName, traceName) + .tag("trace_id", Value.stringTagValue(traceId)) + .tag("span_id", Value.stringTagValue(spanId)) + .tag("service_name", Value.stringTagValue(serviceName)) + .tag("start_time", Value.timestampTagValue(now.toEpochMilli())) + .span(spanData) + .version(1L); + + StreamObserver writeObserver + = client.getTraceServiceStub().write(new StreamObserver() { + @Override + public void onNext(BanyandbTrace.WriteResponse writeResponse) { + assertEquals(BanyandbModel.Status.STATUS_SUCCEED.name(), writeResponse.getStatus()); + } + + @Override + public void onError(Throwable throwable) { + fail("write failed: " + throwable.getMessage()); + } + + @Override + public void onCompleted() { + + } + }); + try { + writeObserver.onNext(traceWrite.build()); + } finally { + writeObserver.onCompleted(); + } + + // Create trace query with trace_id condition + TraceQuery query = new TraceQuery( + Lists.newArrayList(groupName), + traceName, + Collections.emptySet() + ); + query.and(PairQueryCondition.StringQueryCondition.eq("trace_id", traceId)); + + // Execute query with conditions + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + TraceQueryResponse response = client.query(query); + assertNotNull(response); + assertFalse(response.isEmpty()); + assertEquals(1, response.size()); + + // Verify we can access trace data + assertNotNull(response.getTraces()); + assertEquals(1, response.getTraces().size()); + + // Get the first trace and verify its contents + BanyandbTrace.Trace trace = response.getTraces().get(0); + assertNotNull(trace); + assertEquals(1, trace.getSpansCount()); + + // Get the span from the trace and verify its contents + BanyandbTrace.Span span = trace.getSpans(0); + assertNotNull(span); + + // Verify span data (binary content) - this is the main content returned + assertNotNull(span.getSpan()); + assertFalse(span.getSpan().isEmpty()); + assertArrayEquals(spanData, span.getSpan().toByteArray()); + }); + } + + @Test + public void testTraceQueryOrderByStartTime() throws BanyanDBException, ExecutionException, InterruptedException, TimeoutException { + // Test data with different timestamps + String traceId = "trace-order-test-"; + String serviceName = "order-test-service"; + Instant baseTime = Instant.now().minusSeconds(60); // Start 1 minute ago + + // Create 3 traces with different timestamps (1 minute apart) + TraceWrite trace1 = client.createTraceWrite(groupName, traceName) + .tag("trace_id", Value.stringTagValue(traceId + "1")) + .tag("span_id", Value.stringTagValue("span-1")) + .tag("service_name", Value.stringTagValue(serviceName)) + .tag("start_time", Value.timestampTagValue(baseTime.toEpochMilli())) + .span("span-data-1".getBytes()) + .version(1L); + + TraceWrite trace2 = client.createTraceWrite(groupName, traceName) + .tag("trace_id", Value.stringTagValue(traceId + "2")) + .tag("span_id", Value.stringTagValue("span-2")) + .tag("service_name", Value.stringTagValue(serviceName)) + .tag("start_time", Value.timestampTagValue(baseTime.plusSeconds(60).toEpochMilli())) + .span("span-data-2".getBytes()) + .version(1L); + + TraceWrite trace3 = client.createTraceWrite(groupName, traceName) + .tag("trace_id", Value.stringTagValue(traceId + "3")) + .tag("span_id", Value.stringTagValue("span-3")) + .tag("service_name", Value.stringTagValue(serviceName)) + .tag("start_time", Value.timestampTagValue(baseTime.plusSeconds(120).toEpochMilli())) + .span("span-data-3".getBytes()) + .version(1L); + StreamObserver writeObserver + = client.getTraceServiceStub().write(new StreamObserver() { + @Override + public void onNext(BanyandbTrace.WriteResponse writeResponse) { + assertEquals(BanyandbModel.Status.STATUS_SUCCEED.name(), writeResponse.getStatus()); + } + + @Override + public void onError(Throwable throwable) { + fail("write failed: " + throwable.getMessage()); + } + + @Override + public void onCompleted() { + + } + }); + try { + writeObserver.onNext(trace1.build()); + writeObserver.onNext(trace2.build()); + writeObserver.onNext(trace3.build()); + } finally { + writeObserver.onCompleted(); + } + + // Create trace query with order by start_time (no trace_id condition as it interferes with ordering) + TraceQuery query = new TraceQuery( + Lists.newArrayList(groupName), + traceName, + new TimestampRange(baseTime.toEpochMilli(), baseTime.plusSeconds(60).toEpochMilli()), + ImmutableSet.of("start_time") + ); + query.setOrderBy(new AbstractQuery.OrderBy("start_time", AbstractQuery.Sort.DESC)); + + // Execute query and verify ordering + await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { + TraceQueryResponse response = client.query(query); + assertNotNull(response); + assertFalse(response.isEmpty()); + assertEquals(2, response.size()); + + // Verify we can access trace data + assertNotNull(response.getTraces()); + assertEquals(2, response.getTraces().size()); + + // Get spans from each trace and verify that span content matches expected data + BanyandbTrace.Trace firstTrace = response.getTraces().get(0); + BanyandbTrace.Trace secondTrace = response.getTraces().get(1); + + assertEquals(1, firstTrace.getSpansCount()); + assertEquals(1, secondTrace.getSpansCount()); + + String firstSpanContent = new String(firstTrace.getSpans(0).getSpan().toByteArray()); + String secondSpanContent = new String(secondTrace.getSpans(0).getSpan().toByteArray()); + + // Since we're ordering by start_time DESC, span-data-2 should come before span-data-1 + // (baseTime+60 > baseTime) + assertEquals("span-data-2", firstSpanContent, "First span should be span-data-2 (newer timestamp)"); + assertEquals("span-data-1", secondSpanContent, "Second span should be span-data-1 (older timestamp)"); + }); + } + + private BanyandbDatabase.IndexRule buildIndexRule() { + return BanyandbDatabase.IndexRule.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder() + .setGroup(groupName) + .setName("start_time")) + .addTags("start_time") + .setType(BanyandbDatabase.IndexRule.Type.TYPE_TREE) + .build(); + } + + private BanyandbDatabase.IndexRuleBinding buildIndexRuleBinding() { + return BanyandbDatabase.IndexRuleBinding.newBuilder() + .setMetadata(BanyandbCommon.Metadata.newBuilder() + .setGroup(groupName) + .setName("trace_binding")) + .setSubject(BanyandbDatabase.Subject.newBuilder() + .setCatalog( + BanyandbCommon.Catalog.CATALOG_TRACE) + .setName(traceName)) + .addAllRules(Arrays.asList("start_time")) + .setBeginAt(TimeUtils.buildTimestamp( + ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC))) + .setExpireAt(TimeUtils.buildTimestamp(DEFAULT_EXPIRE_AT)) + .build(); + } +} \ No newline at end of file diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/ExceptionTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/ExceptionTest.java new file mode 100644 index 000000000000..c6f22533875e --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/ExceptionTest.java @@ -0,0 +1,65 @@ +/* + * 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.library.banyandb.v1.client.grpc; + +import io.grpc.Status; +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.IndexRuleRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.AbstractBanyanDBClientTest; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.IndexRuleMetadataRegistry; +import java.io.IOException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.AdditionalAnswers.delegatesTo; +import static org.mockito.Mockito.mock; + +public class ExceptionTest extends AbstractBanyanDBClientTest { + @BeforeEach + public void setUp() throws IOException { + super.setUp(); + } + + @Test + public void testStatusInvalidArgument() { + final IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase serviceImpl = + mock(IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase.class, delegatesTo( + new IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase() { + @Override + public void get(BanyandbDatabase.IndexRuleRegistryServiceGetRequest request, StreamObserver responseObserver) { + responseObserver.onError(Status.INVALID_ARGUMENT.withDescription("invalid arg").asRuntimeException()); + } + })); + + serviceRegistry.addService(serviceImpl); + + try { + new IndexRuleMetadataRegistry(this.channel).get("group", "trace_id"); + fail(); + } catch (BanyanDBException ex) { + assertEquals(Status.Code.INVALID_ARGUMENT, ex.getStatus()); + assertTrue(ex.getMessage().contains("invalid arg")); + } + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManagerTest.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManagerTest.java new file mode 100644 index 000000000000..57969a4aee86 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/ChannelManagerTest.java @@ -0,0 +1,145 @@ +/* + * 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.library.banyandb.v1.client.grpc.channel; + +import com.google.common.collect.ImmutableList; +import io.grpc.CallOptions; +import io.grpc.ConnectivityState; +import io.grpc.ManagedChannel; +import io.grpc.MethodDescriptor; +import io.grpc.Server; +import io.grpc.Status; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; +import org.apache.skywalking.banyandb.database.v1.IndexRuleRegistryServiceGrpc; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.IndexRuleMetadataRegistry; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import java.io.IOException; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.mockito.AdditionalAnswers.delegatesTo; +import static org.mockito.Mockito.mock; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ChannelManagerTest { + + @Test + public void testAuthority() throws IOException { + final ManagedChannel ch = mock(ManagedChannel.class); + + Mockito.when(ch.authority()).thenReturn("myAuth"); + + ChannelManager manager = + ChannelManager.create( + ChannelManagerSettings.builder() + .refreshInterval(30) + .forceReconnectionThreshold(10).build(), + new FakeChannelFactory(ch)); + assertEquals("myAuth", manager.authority()); + } + + @Test + public void channelRefreshShouldSwapChannel() throws IOException { + ManagedChannel underlyingChannel1 = mock(ManagedChannel.class); + ManagedChannel underlyingChannel2 = mock(ManagedChannel.class); + + // mock executor service to capture the runnable scheduled, so we can invoke it when we want to + ScheduledExecutorService scheduledExecutorService = + mock(ScheduledExecutorService.class); + + Mockito.doReturn(null) + .when(scheduledExecutorService) + .schedule( + Mockito.any(Runnable.class), Mockito.anyLong(), Mockito.eq(TimeUnit.MILLISECONDS)); + + ChannelManager manager = + new ChannelManager( + ChannelManagerSettings.builder() + .refreshInterval(30) + .forceReconnectionThreshold(1).build(), + new FakeChannelFactory(ImmutableList.of(underlyingChannel1, underlyingChannel2)), + scheduledExecutorService); + Mockito.reset(underlyingChannel1); + + manager.newCall(FakeMethodDescriptor.create(), CallOptions.DEFAULT); + + Mockito.verify(underlyingChannel1, Mockito.only()) + .newCall(Mockito.>any(), Mockito.any(CallOptions.class)); + + // set status to needReconnect=true + manager.entryRef.get().needReconnect = true; + // and return false for connection status + Mockito.doReturn(ConnectivityState.TRANSIENT_FAILURE) + .when(underlyingChannel1) + .getState(Mockito.anyBoolean()); + + // swap channel + manager.refresh(); + + manager.newCall(FakeMethodDescriptor.create(), CallOptions.DEFAULT); + + Mockito.verify(underlyingChannel2, Mockito.only()) + .newCall(Mockito.>any(), Mockito.any(CallOptions.class)); + } + + @Test + public void networkErrorStatusShouldTriggerReconnect() throws IOException { + final IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase indexRuleServiceImpl = + mock(IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase.class, delegatesTo( + new IndexRuleRegistryServiceGrpc.IndexRuleRegistryServiceImplBase() { + @Override + public void get(BanyandbDatabase.IndexRuleRegistryServiceGetRequest request, StreamObserver responseObserver) { + responseObserver.onError(Status.UNAVAILABLE.asRuntimeException()); + } + })); + // Generate a unique in-process server name. + String serverName = InProcessServerBuilder.generateName(); + + // Create a server, add service, start, and register for automatic graceful shutdown. + InProcessServerBuilder serverBuilder = InProcessServerBuilder + .forName(serverName).directExecutor() + .addService(indexRuleServiceImpl); + final Server s = serverBuilder.build(); + s.start(); + // Create a client channel and register for automatic graceful shutdown. + ManagedChannel ch = InProcessChannelBuilder.forName(serverName).directExecutor().build(); + ChannelManager manager = + ChannelManager.create( + ChannelManagerSettings.builder() + .refreshInterval(30) + .forceReconnectionThreshold(10).build(), + new FakeChannelFactory(ch)); + + try { + new IndexRuleMetadataRegistry(manager).get("default", "sw"); + fail(); + } catch (BanyanDBException ex) { + assertEquals(Status.Code.UNAVAILABLE, ex.getStatus()); + } + + assertTrue(manager.entryRef.get().needReconnect); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/FakeChannelFactory.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/FakeChannelFactory.java new file mode 100644 index 000000000000..1c3cfe5572b8 --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/FakeChannelFactory.java @@ -0,0 +1,41 @@ +/* + * 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.library.banyandb.v1.client.grpc.channel; + +import com.google.common.collect.ImmutableList; +import io.grpc.ManagedChannel; +import java.util.List; + +public class FakeChannelFactory implements ChannelFactory { + private int called = 0; + private List channels; + + public FakeChannelFactory(List channels) { + this.channels = channels; + } + + public FakeChannelFactory(ManagedChannel... channels) { + this.channels = ImmutableList.copyOf(channels); + } + + @Override + public ManagedChannel create() { + return channels.get(called++); + } +} diff --git a/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/FakeMethodDescriptor.java b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/FakeMethodDescriptor.java new file mode 100644 index 000000000000..bb783d996d8c --- /dev/null +++ b/oap-server/server-library/library-banyandb-client/src/test/java/org/apache/skywalking/library/banyandb/v1/client/grpc/channel/FakeMethodDescriptor.java @@ -0,0 +1,53 @@ +/* + * 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.library.banyandb.v1.client.grpc.channel; + +import io.grpc.MethodDescriptor; +import java.io.InputStream; + +public class FakeMethodDescriptor { + private FakeMethodDescriptor() { + } + + public static MethodDescriptor create() { + return create(MethodDescriptor.MethodType.UNARY, "FakeClient/fake-method"); + } + + public static MethodDescriptor create( + MethodDescriptor.MethodType type, String name) { + return MethodDescriptor.newBuilder() + .setType(MethodDescriptor.MethodType.UNARY) + .setFullMethodName(name) + .setRequestMarshaller(new FakeMarshaller()) + .setResponseMarshaller(new FakeMarshaller()) + .build(); + } + + private static class FakeMarshaller implements MethodDescriptor.Marshaller { + @Override + public T parse(InputStream stream) { + throw new UnsupportedOperationException("FakeMarshaller doesn't actually do anything"); + } + + @Override + public InputStream stream(T value) { + throw new UnsupportedOperationException("FakeMarshaller doesn't actually do anything"); + } + } +} diff --git a/oap-server/server-starter/src/main/resources/bydb.dependencies.properties b/oap-server/server-library/library-banyandb-client/src/test/resources/config.yaml similarity index 58% rename from oap-server/server-starter/src/main/resources/bydb.dependencies.properties rename to oap-server/server-library/library-banyandb-client/src/test/resources/config.yaml index d39c334c4f4c..286d88a2d632 100644 --- a/oap-server/server-starter/src/main/resources/bydb.dependencies.properties +++ b/oap-server/server-library/library-banyandb-client/src/test/resources/config.yaml @@ -13,12 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -# BanyanDB version is the version number of BanyanDB Server release. -# This is the bundled and tested BanyanDB release version -bydb.version=0.9 -# BanyanDB API version is the version number of the BanyanDB query APIs -# OAP server has bundled implementation of BanyanDB Java client. -# Please check BanyanDB documentation for the API version compatibility. -# https://skywalking.apache.org/docs/skywalking-banyandb/next/installation/versions -# Each `bydb.api.version` could have multiple compatible release version(`bydb.version`). -bydb.api.version=0.9 \ No newline at end of file +users: + - username: admin + password: 123456 + - username: test + password: 123456 \ No newline at end of file diff --git a/oap-server/server-library/pom.xml b/oap-server/server-library/pom.xml index 93481db0742a..84eeae326074 100644 --- a/oap-server/server-library/pom.xml +++ b/oap-server/server-library/pom.xml @@ -38,5 +38,6 @@ library-async-profiler-jfr-parser library-pprof-parser library-integration-test + library-banyandb-client diff --git a/oap-server/server-starter/pom.xml b/oap-server/server-starter/pom.xml index 7d44453471ae..35b5e7de81be 100644 --- a/oap-server/server-starter/pom.xml +++ b/oap-server/server-starter/pom.xml @@ -320,7 +320,6 @@ metadata-service-mapping.yaml trace-sampling-policy-settings.yml hierarchy-definition.yml - bydb.dependencies.properties bydb.yml bydb-topn.yml oal/ diff --git a/oap-server/server-starter/src/main/resources/bydb.yml b/oap-server/server-starter/src/main/resources/bydb.yml index 496d6314c543..4a2b94693557 100644 --- a/oap-server/server-starter/src/main/resources/bydb.yml +++ b/oap-server/server-starter/src/main/resources/bydb.yml @@ -53,6 +53,8 @@ global: # The namespace in BanyanDB to store the data of OAP, if not set, the default is "sw". # OAP will create BanyanDB Groups using the format of "{namespace}_{group name}", such as "sw_records". namespace: ${SW_NAMESPACE:"sw"} + # The compatible server API versions of BanyanDB. + compatibleServerApiVersions: ${SW_STORAGE_BANYANDB_COMPATIBLE_SERVER_API_VERSIONS:"0.9"} groups: # The group settings of record. diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/pom.xml b/oap-server/server-storage-plugin/storage-banyandb-plugin/pom.xml index 8bc6a65134d9..7dbb49b705e9 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/pom.xml +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/pom.xml @@ -46,7 +46,8 @@ org.apache.skywalking - banyandb-java-client + library-banyandb-client + ${project.version} org.apache.skywalking diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java index d44e87e87647..c958df4ec276 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBAggregationQueryDAO.java @@ -22,12 +22,12 @@ import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; -import org.apache.skywalking.banyandb.v1.client.TopNQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.TopNQueryResponse; import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics; import org.apache.skywalking.oap.server.core.query.enumeration.Order; import org.apache.skywalking.oap.server.core.query.enumeration.Scope; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBConverter.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBConverter.java index 24256e0dae1a..b8fcdcedf06f 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBConverter.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBConverter.java @@ -22,14 +22,14 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureWrite; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamWrite; -import org.apache.skywalking.banyandb.v1.client.TagAndValue; -import org.apache.skywalking.banyandb.v1.client.TraceWrite; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; -import org.apache.skywalking.banyandb.v1.client.metadata.Serializable; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureWrite; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamWrite; +import org.apache.skywalking.library.banyandb.v1.client.TagAndValue; +import org.apache.skywalking.library.banyandb.v1.client.TraceWrite; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Serializable; import org.apache.skywalking.oap.server.core.analysis.Layer; import org.apache.skywalking.oap.server.core.profiling.trace.ProfileLanguageType; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; @@ -99,7 +99,8 @@ public void accept(String fieldName, Object fieldValue) { "it should be an internal error, please submit an issue to the SkyWalking community"); } try { - this.streamWrite.tag(fieldName, buildTag(fieldValue, columnSpec.getColumnClass())); + String tagFamily = this.schema.getTags().get(fieldName); + this.streamWrite.tag(tagFamily, fieldName, buildTag(fieldValue, columnSpec.getColumnClass())); } catch (BanyanDBException ex) { log.error("fail to add tag", ex); } @@ -108,7 +109,8 @@ public void accept(String fieldName, Object fieldValue) { @Override public void accept(String fieldName, byte[] fieldValue) { try { - this.streamWrite.tag(fieldName, TagAndValue.binaryTagValue(fieldValue)); + String tagFamily = this.schema.getTags().get(fieldName); + this.streamWrite.tag(tagFamily, fieldName, TagAndValue.binaryTagValue(fieldValue)); } catch (BanyanDBException ex) { log.error("fail to add tag", ex); } @@ -117,7 +119,8 @@ public void accept(String fieldName, byte[] fieldValue) { @Override public void accept(String fieldName, List fieldValue) { try { - this.streamWrite.tag(fieldName, TagAndValue.stringArrayTagValue(fieldValue)); + String tagFamily = this.schema.getTags().get(fieldName); + this.streamWrite.tag(tagFamily, fieldName, TagAndValue.stringArrayTagValue(fieldValue)); } catch (BanyanDBException ex) { log.error("fail to accept string array tag", ex); } @@ -151,7 +154,8 @@ public void accept(String fieldName, Object fieldValue) { } try { if (columnSpec.getColumnType() == MetadataRegistry.ColumnType.TAG) { - this.measureWrite.tag(fieldName, buildTag(fieldValue, columnSpec.getColumnClass())); + String tagFamily = this.schema.getTags().get(fieldName); + this.measureWrite.tag(tagFamily, fieldName, buildTag(fieldValue, columnSpec.getColumnClass())); } else { this.measureWrite.field(fieldName, buildField(fieldValue, columnSpec.getColumnClass())); } @@ -162,7 +166,8 @@ public void accept(String fieldName, Object fieldValue) { public void acceptID(String id) { try { - this.measureWrite.tag(ID, TagAndValue.stringTagValue(id)); + String tagFamily = this.schema.getTags().get(ID); + this.measureWrite.tag(tagFamily, ID, TagAndValue.stringTagValue(id)); } catch (BanyanDBException ex) { log.error("fail to add ID tag", ex); } @@ -173,7 +178,8 @@ public void accept(String fieldName, byte[] fieldValue) { MetadataRegistry.ColumnSpec columnSpec = this.schema.getSpec(fieldName); try { if (columnSpec.getColumnType() == MetadataRegistry.ColumnType.TAG) { - this.measureWrite.tag(fieldName, TagAndValue.binaryTagValue(fieldValue)); + String tagFamily = this.schema.getTags().get(fieldName); + this.measureWrite.tag(tagFamily, fieldName, TagAndValue.binaryTagValue(fieldValue)); } else { this.measureWrite.field(fieldName, TagAndValue.binaryFieldValue(fieldValue)); } @@ -185,7 +191,8 @@ public void accept(String fieldName, byte[] fieldValue) { @Override public void accept(String fieldName, List fieldValue) { try { - this.measureWrite.tag(fieldName, TagAndValue.stringArrayTagValue(fieldValue)); + String tagFamily = this.schema.getTags().get(fieldName); + this.measureWrite.tag(tagFamily, fieldName, TagAndValue.stringArrayTagValue(fieldValue)); } catch (BanyanDBException ex) { log.error("fail to accept string array tag", ex); } @@ -254,6 +261,7 @@ public void accept(String fieldName, List fieldValue) { return; } try { + String tagFamily = this.schema.getTags().get(fieldName); this.traceWrite.tag(fieldName, TagAndValue.stringArrayTagValue(fieldValue)); } catch (BanyanDBException ex) { log.error("fail to accept string array tag", ex); diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIndexInstaller.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIndexInstaller.java index 7067da460b6a..b1e014867a58 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIndexInstaller.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIndexInstaller.java @@ -39,10 +39,9 @@ import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRule; import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.IndexRuleBinding; import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TopNAggregation; -import org.apache.skywalking.banyandb.v1.client.BanyanDBClient; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; -import org.apache.skywalking.banyandb.v1.client.metadata.MetadataCache; -import org.apache.skywalking.banyandb.v1.client.metadata.ResourceExist; +import org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.metadata.ResourceExist; import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.RunningMode; import org.apache.skywalking.oap.server.core.analysis.DownSampling; @@ -84,9 +83,9 @@ public InstallInfo isExists(Model model) throws StorageException { final BanyanDBClient c = ((BanyanDBStorageClient) this.client).client; // first check resource existence and create group if necessary final ResourceExist resourceExist = checkResourceExistence(metadata, c); - installInfo.setGroupExist(resourceExist.hasGroup()); - installInfo.setTableExist(resourceExist.hasResource()); - if (!resourceExist.hasResource() && !BanyanDBTrace.MergeTable.class.isAssignableFrom(model.getStreamClass())) { + installInfo.setGroupExist(resourceExist.isHasGroup()); + installInfo.setTableExist(resourceExist.isHasResource()); + if (!resourceExist.isHasResource() && !BanyanDBTrace.MergeTable.class.isAssignableFrom(model.getStreamClass())) { installInfo.setAllExist(false); return installInfo; } else { @@ -134,11 +133,6 @@ public InstallInfo isExists(Model model) throws StorageException { checkTopNAggregation(model, c); } } - // pre-load remote schema for java client - MetadataCache.EntityMetadata remoteMeta = updateSchemaFromServer(metadata, c); - if (remoteMeta == null) { - throw new IllegalStateException("inconsistent state: metadata:" + metadata + ", remoteMeta: null"); - } } else { PropertyModel propertyModel = MetadataRegistry.INSTANCE.registerPropertyModel(model, config); if (!RunningMode.isNoInitMode()) { @@ -395,7 +389,7 @@ private ResourceExist checkResourceExistence(MetadataRegistry.SchemaMetadata met if (!RunningMode.isNoInitMode()) { if (!groupAligned.contains(metadata.getGroup())) { // create the group if not exist - if (!resourceExist.hasGroup()) { + if (!resourceExist.isHasGroup()) { try { Group g = client.define(gBuilder.build()); if (g != null) { @@ -422,22 +416,6 @@ private ResourceExist checkResourceExistence(MetadataRegistry.SchemaMetadata met return resourceExist; } - /** - * Update the schema from the banyanDB server side for the java client cache - */ - private MetadataCache.EntityMetadata updateSchemaFromServer(MetadataRegistry.SchemaMetadata metadata, BanyanDBClient client) throws BanyanDBException { - switch (metadata.getKind()) { - case STREAM: - return client.updateStreamMetadataCacheFromSever(metadata.getGroup(), metadata.name()); - case MEASURE: - return client.updateMeasureMetadataCacheFromSever(metadata.getGroup(), metadata.name()); - case TRACE: - return client.updateTraceMetadataCacheFromServer(metadata.getGroup(), metadata.name()); - default: - throw new IllegalStateException("unknown metadata kind: " + metadata.getKind()); - } - } - private void defineTopNAggregation(MetadataRegistry.Schema schema, BanyanDBClient client) throws BanyanDBException { if (CollectionUtils.isEmpty(schema.getTopNSpecs())) { if (schema.getMetadata().getKind() == MetadataRegistry.Kind.MEASURE) { diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBNoneStreamDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBNoneStreamDAO.java index 51ce5381ac6f..09bd256e14a4 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBNoneStreamDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBNoneStreamDAO.java @@ -19,7 +19,7 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.banyandb.v1.client.StreamWrite; +import org.apache.skywalking.library.banyandb.v1.client.StreamWrite; import org.apache.skywalking.oap.server.core.analysis.config.NoneStream; import org.apache.skywalking.oap.server.core.storage.AbstractDAO; import org.apache.skywalking.oap.server.core.storage.INoneStreamDAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java index 62515b86df43..61888bcc024a 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBRecordsQueryDAO.java @@ -19,10 +19,10 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.analysis.topn.TopN; import org.apache.skywalking.oap.server.core.query.enumeration.Order; import org.apache.skywalking.oap.server.core.query.input.Duration; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageClient.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageClient.java index 23a4beaa327e..eee91772d89e 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageClient.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageClient.java @@ -22,11 +22,9 @@ import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; import java.io.IOException; -import java.io.InputStream; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; @@ -38,24 +36,24 @@ import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.DeleteResponse; import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.Property; import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; -import org.apache.skywalking.banyandb.v1.client.BanyanDBClient; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.MeasureWrite; -import org.apache.skywalking.banyandb.v1.client.Options; -import org.apache.skywalking.banyandb.v1.client.PropertyStore; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; -import org.apache.skywalking.banyandb.v1.client.StreamWrite; -import org.apache.skywalking.banyandb.v1.client.TopNQuery; -import org.apache.skywalking.banyandb.v1.client.TopNQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TraceQuery; -import org.apache.skywalking.banyandb.v1.client.TraceQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TraceWrite; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.InternalException; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.InvalidArgumentException; -import org.apache.skywalking.banyandb.v1.client.util.StatusUtil; +import org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.MeasureWrite; +import org.apache.skywalking.library.banyandb.v1.client.Options; +import org.apache.skywalking.library.banyandb.v1.client.PropertyStore; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.StreamWrite; +import org.apache.skywalking.library.banyandb.v1.client.TopNQuery; +import org.apache.skywalking.library.banyandb.v1.client.TopNQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TraceQuery; +import org.apache.skywalking.library.banyandb.v1.client.TraceQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TraceWrite; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.InternalException; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.InvalidArgumentException; +import org.apache.skywalking.library.banyandb.v1.client.util.StatusUtil; import org.apache.skywalking.oap.server.library.client.Client; import org.apache.skywalking.oap.server.library.client.healthcheck.DelegatedHealthChecker; import org.apache.skywalking.oap.server.library.client.healthcheck.HealthCheckable; @@ -79,7 +77,7 @@ */ @Slf4j public class BanyanDBStorageClient implements Client, HealthCheckable { - private static final String[] COMPATIBLE_SERVER_API_VERSIONS = {"0.9"}; + private final String[] compatibleServerApiVersions; final BanyanDBClient client; private final DelegatedHealthChecker healthChecker = new DelegatedHealthChecker(); private final int flushTimeout; @@ -107,32 +105,17 @@ public BanyanDBStorageClient(ModuleManager moduleManager, BanyanDBStorageConfig } else if (StringUtil.isNotBlank(password)) { throw new IllegalArgumentException("Password is set, but user is not set."); } - this.client = new BanyanDBClient(config.getTargetArray(), options); + this.client = new BanyanDBClient(config.getGlobal().getTargets(), options); this.flushTimeout = config.getGlobal().getFlushTimeout(); this.options = options; this.moduleManager = moduleManager; + this.compatibleServerApiVersions = config.getGlobal().getCompatibleServerApiVersions(); } @Override public void connect() throws Exception { initTelemetry(); this.client.connect(); - final Properties properties = new Properties(); - try (final InputStream resourceAsStream - = BanyanDBStorageClient.class.getClassLoader() - .getResourceAsStream( - "bydb.dependencies.properties")) { - if (resourceAsStream == null) { - throw new IllegalStateException("bydb.dependencies.properties not found"); - } - properties.load(resourceAsStream); - } - final String expectedApiVersion = properties.getProperty("bydb.api.version"); - if (!Arrays.stream(COMPATIBLE_SERVER_API_VERSIONS).anyMatch(v -> v.equals(expectedApiVersion))) { - throw new IllegalStateException("Inconsistent versions between bydb.dependencies.properties and codes(" + - String.join(", ", COMPATIBLE_SERVER_API_VERSIONS) + ")."); - } - BanyandbCommon.APIVersion apiVersion; try { apiVersion = this.client.getAPIVersion(); @@ -146,14 +129,14 @@ public void connect() throws Exception { } throw e; } - final boolean isCompatible = Arrays.stream(COMPATIBLE_SERVER_API_VERSIONS) + final boolean isCompatible = Arrays.stream(compatibleServerApiVersions) .anyMatch(v -> v.equals(apiVersion.getVersion())); final String revision = apiVersion.getRevision(); log.info("BanyanDB server API version: {}, revision: {}", apiVersion.getVersion(), revision); if (!isCompatible) { throw new IllegalStateException( "Incompatible BanyanDB server API version: " + apiVersion.getVersion() + ". But accepted versions: " - + String.join(", ", COMPATIBLE_SERVER_API_VERSIONS)); + + String.join(", ", compatibleServerApiVersions)); } } @@ -374,20 +357,10 @@ public void onNext(BanyandbStream.WriteResponse writeResponse) { break; case STATUS_EXPIRED_SCHEMA: BanyandbCommon.Metadata metadata = writeResponse.getMetadata(); - log.warn( - "The schema {}.{} is expired, trying update the schema...", + log.error( + "The schema {}.{} is expired", metadata.getGroup(), metadata.getName() ); - try { - client.updateStreamMetadataCacheFromSever( - metadata.getGroup(), metadata.getName()); - } catch (BanyanDBException e) { - String warnMessage = String.format( - "Failed to refresh the stream schema %s.%s", - metadata.getGroup(), metadata.getName() - ); - log.warn(warnMessage, e); - } responseException = new InvalidArgumentException( "Expired revision: " + metadata.getModRevision(), null, Status.Code.INVALID_ARGUMENT, true diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageConfig.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageConfig.java index 97da501178ce..1475fb8c1914 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageConfig.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageConfig.java @@ -53,11 +53,6 @@ public class BanyanDBStorageConfig extends ModuleConfig { private Map/*ruleName, topN*/> topNConfigs = new HashMap<>(); - public String[] getTargetArray() { - return Iterables.toArray( - Splitter.on(",").omitEmptyStrings().trimResults().split(this.global.targets), String.class); - } - @Getter @Setter public static class Global { @@ -112,6 +107,17 @@ public static class Global { private int profileDataQueryBatchSize = 100; private boolean cleanupUnusedTopNRules = true; private String namespace = "sw"; + private String compatibleServerApiVersions; + + public String[] getTargets() { + return Iterables.toArray( + Splitter.on(",").omitEmptyStrings().trimResults().split(this.targets), String.class); + } + + public String[] getCompatibleServerApiVersions() { + return Iterables.toArray( + Splitter.on(",").omitEmptyStrings().trimResults().split(this.compatibleServerApiVersions), String.class); + } } // The configuration of the groups. diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java index 47e81cfc1d37..134c8f364a56 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBStorageProvider.java @@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.RunningMode; import org.apache.skywalking.oap.server.core.storage.IBatchDAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUIMenuManagementDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUIMenuManagementDAO.java index 658034f6bb8e..ba15aceb8f64 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUIMenuManagementDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUIMenuManagementDAO.java @@ -21,7 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.TagAndValue; +import org.apache.skywalking.library.banyandb.v1.client.TagAndValue; import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.Property; import org.apache.skywalking.oap.server.core.management.ui.menu.UIMenu; import org.apache.skywalking.oap.server.core.storage.management.UIMenuManagementDAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUITemplateManagementDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUITemplateManagementDAO.java index 5aa40a0c5550..5b93f785389f 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUITemplateManagementDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBUITemplateManagementDAO.java @@ -21,7 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.TagAndValue; +import org.apache.skywalking.library.banyandb.v1.client.TagAndValue; import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.Property; import org.apache.skywalking.oap.server.core.management.ui.template.UITemplate; import org.apache.skywalking.oap.server.core.query.input.DashboardSetting; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java index 813a4eb0c43b..ad6c2911b451 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/MetadataRegistry.java @@ -46,10 +46,10 @@ import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TraceTagSpec; import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TagType; import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase.TopNAggregation; -import org.apache.skywalking.banyandb.v1.client.AbstractCriteria; -import org.apache.skywalking.banyandb.v1.client.And; -import org.apache.skywalking.banyandb.v1.client.PairQueryCondition; -import org.apache.skywalking.banyandb.v1.client.metadata.Duration; +import org.apache.skywalking.library.banyandb.v1.client.AbstractCriteria; +import org.apache.skywalking.library.banyandb.v1.client.And; +import org.apache.skywalking.library.banyandb.v1.client.PairQueryCondition; +import org.apache.skywalking.library.banyandb.v1.client.metadata.Duration; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.metrics.IntList; import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics; @@ -114,7 +114,7 @@ public StreamModel registerStreamModel(Model model, BanyanDBStorageConfig config // iterate over tagFamilySpecs to save tag names for (final TagFamilySpec tagFamilySpec : tagFamilySpecs) { for (final TagSpec tagSpec : tagFamilySpec.getTagsList()) { - schemaBuilder.tag(tagSpec.getName()); + schemaBuilder.tag(tagSpec.getName(), tagFamilySpec.getName()); } } String timestampColumn4Stream = model.getBanyanDBModelExtension().getTimestampColumn(); @@ -164,12 +164,11 @@ public MeasureModel registerMeasureModel(Model model, BanyanDBStorageConfig conf ); List tagFamilySpecs = schemaMetadata.extractTagFamilySpec(tagsAndFields.tags); // iterate over tagFamilySpecs to save tag names - Set tags = tagFamilySpecs.stream() - .flatMap(tagFamilySpec -> tagFamilySpec.getTagsList().stream()) - - .map(TagSpec::getName) - .collect(Collectors.toSet()); - schemaBuilder.tags(tags); + for (final TagFamilySpec tagFamilySpec : tagFamilySpecs) { + for (final TagSpec tagSpec : tagFamilySpec.getTagsList()) { + schemaBuilder.tag(tagSpec.getName(), tagFamilySpec.getName()); + } + } List indexRules = tagsAndFields.tags.stream() .map(TagMetadata::getIndexRule) .filter(Objects::nonNull) @@ -199,7 +198,7 @@ public MeasureModel registerMeasureModel(Model model, BanyanDBStorageConfig conf schemaBuilder.topNSpecs(parseTopNSpecs( model, schemaMetadata.group, schemaMetadata.name(), config.getTopNConfigs().get(model.getName()), - tags + new HashSet<>(schemaBuilder.tags$key) )); registry.put(schemaMetadata.name(), schemaBuilder.build()); return new MeasureModel(builder.build(), indexRules); @@ -249,7 +248,8 @@ public TraceModel registerTraceModel(Model model, BanyanDBStorageConfig config) } builder.addTags(traceTagSpec.build()); schemaBuilder.spec(columnStorageName, new ColumnSpec(ColumnType.TAG, col.getType())); - schemaBuilder.tag(tagSpec.getName()); + // trace tag does not have tag family + schemaBuilder.tag(tagSpec.getName(), null); } List traceIndexRules = model.getBanyanDBModelExtension().getTraceIndexRules(); @@ -853,7 +853,6 @@ public String name() { public String indexFamily() { switch (kind) { case MEASURE: - return "default"; case STREAM: return "searchable"; default: @@ -896,9 +895,13 @@ public static class Schema { @Singular private final Map specs; + /** + * key:tagName, value:tagFamilyName + * Notice: for trace, tagFamilyName is always null; for property, does not have tags. + */ @Getter @Singular - private final Set tags; + private final Map tags; @Getter @Singular diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/AbstractBulkWriteProcessor.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/AbstractBulkWriteProcessor.java index 7c32fb3fa439..3c85f7781302 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/AbstractBulkWriteProcessor.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/AbstractBulkWriteProcessor.java @@ -31,7 +31,7 @@ import lombok.Getter; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.banyandb.v1.client.AbstractWrite; +import org.apache.skywalking.library.banyandb.v1.client.AbstractWrite; import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics; @Slf4j @@ -154,19 +154,32 @@ protected CompletableFuture doFlush(final List data, HistogramMetr = this.buildStreamObserver(stub.withDeadlineAfter(timeout, TimeUnit.SECONDS), batch); try { - data.forEach(h -> { + AbstractWrite entityWithMetadata = null; + for (Holder h : data) { AbstractWrite entity = (AbstractWrite) h.getWriteEntity(); REQ request; try { - request = entity.build(); + if (entityWithMetadata == null + || !(entityWithMetadata.getEntityMetadata() + .getGroup() + .equals(entity.getEntityMetadata().getGroup()) + && entityWithMetadata.getEntityMetadata() + .getName() + .equals(entity.getEntityMetadata().getName()))) { + entityWithMetadata = entity; + request = entity.build(); + } else { + // Avoid build/write metadata/tags spec again and again for the same entity type in a bulk. + request = entity.buildOnlyValues(); + } } catch (Throwable bt) { log.error("building the entity fails: {}", entity.toString(), bt); h.getFuture().completeExceptionally(bt); - return; + break; } writeRequestStreamObserver.onNext(request); h.getFuture().complete(null); - }); + } } finally { writeRequestStreamObserver.onCompleted(); } diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/MeasureBulkWriteProcessor.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/MeasureBulkWriteProcessor.java index 81303fac8a6e..ea321c101ab4 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/MeasureBulkWriteProcessor.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/MeasureBulkWriteProcessor.java @@ -19,9 +19,7 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.bulk; import io.grpc.stub.StreamObserver; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.CompletableFuture; import javax.annotation.concurrent.ThreadSafe; import lombok.extern.slf4j.Slf4j; @@ -29,10 +27,9 @@ import org.apache.skywalking.banyandb.measure.v1.BanyandbMeasure; import org.apache.skywalking.banyandb.measure.v1.MeasureServiceGrpc; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.BanyanDBClient; -import org.apache.skywalking.banyandb.v1.client.Options; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; -import org.apache.skywalking.banyandb.v1.client.util.StatusUtil; +import org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient; +import org.apache.skywalking.library.banyandb.v1.client.Options; +import org.apache.skywalking.library.banyandb.v1.client.util.StatusUtil; import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics; /** @@ -72,8 +69,6 @@ public MeasureBulkWriteProcessor( protected StreamObserver buildStreamObserver(MeasureServiceGrpc.MeasureServiceStub stub, CompletableFuture batch) { return stub.write(new StreamObserver() { - private final Set schemaExpired = new HashSet<>(); - @Override public void onNext(BanyandbMeasure.WriteResponse writeResponse) { BanyandbModel.Status status = StatusUtil.convertStringToStatus(writeResponse.getStatus()); @@ -83,15 +78,7 @@ public void onNext(BanyandbMeasure.WriteResponse writeResponse) { case STATUS_EXPIRED_SCHEMA: BanyandbCommon.Metadata metadata = writeResponse.getMetadata(); String schemaKey = metadata.getGroup() + "." + metadata.getName(); - if (!schemaExpired.contains(schemaKey)) { - log.warn("The schema {} is expired, trying update the schema...", schemaKey); - try { - client.updateMeasureMetadataCacheFromSever(metadata.getGroup(), metadata.getName()); - schemaExpired.add(schemaKey); - } catch (BanyanDBException e) { - log.error(e.getMessage(), e); - } - } + log.error("The schema {} is expired", schemaKey); break; default: log.warn("Write measure failed with status: {}", status); diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/StreamBulkWriteProcessor.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/StreamBulkWriteProcessor.java index 4fb42030bbf7..6125a5865c9b 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/StreamBulkWriteProcessor.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/StreamBulkWriteProcessor.java @@ -19,9 +19,7 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.bulk; import io.grpc.stub.StreamObserver; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.CompletableFuture; import javax.annotation.concurrent.ThreadSafe; import lombok.extern.slf4j.Slf4j; @@ -29,10 +27,9 @@ import org.apache.skywalking.banyandb.model.v1.BanyandbModel; import org.apache.skywalking.banyandb.stream.v1.BanyandbStream; import org.apache.skywalking.banyandb.stream.v1.StreamServiceGrpc; -import org.apache.skywalking.banyandb.v1.client.BanyanDBClient; -import org.apache.skywalking.banyandb.v1.client.Options; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; -import org.apache.skywalking.banyandb.v1.client.util.StatusUtil; +import org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient; +import org.apache.skywalking.library.banyandb.v1.client.Options; +import org.apache.skywalking.library.banyandb.v1.client.util.StatusUtil; import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics; /** @@ -74,8 +71,6 @@ public StreamBulkWriteProcessor( protected StreamObserver buildStreamObserver(StreamServiceGrpc.StreamServiceStub stub, CompletableFuture batch) { return stub.write( new StreamObserver() { - private final Set schemaExpired = new HashSet<>(); - @Override public void onNext(BanyandbStream.WriteResponse writeResponse) { BanyandbModel.Status status = StatusUtil.convertStringToStatus(writeResponse.getStatus()); @@ -85,15 +80,7 @@ public void onNext(BanyandbStream.WriteResponse writeResponse) { case STATUS_EXPIRED_SCHEMA: BanyandbCommon.Metadata metadata = writeResponse.getMetadata(); String schemaKey = metadata.getGroup() + "." + metadata.getName(); - if (!schemaExpired.contains(schemaKey)) { - log.warn("The schema {} is expired, trying update the schema...", schemaKey); - try { - client.updateStreamMetadataCacheFromSever(metadata.getGroup(), metadata.getName()); - schemaExpired.add(schemaKey); - } catch (BanyanDBException e) { - log.error(e.getMessage(), e); - } - } + log.error("The schema {} is expired", schemaKey); break; default: log.warn("Write stream failed with status: {}", status); diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/TraceBulkWriteProcessor.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/TraceBulkWriteProcessor.java index 3e8914b9d26a..eb04e014a093 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/TraceBulkWriteProcessor.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/bulk/TraceBulkWriteProcessor.java @@ -19,9 +19,7 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.bulk; import io.grpc.stub.StreamObserver; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.CompletableFuture; import javax.annotation.concurrent.ThreadSafe; import lombok.extern.slf4j.Slf4j; @@ -29,10 +27,9 @@ import org.apache.skywalking.banyandb.model.v1.BanyandbModel; import org.apache.skywalking.banyandb.trace.v1.BanyandbTrace; import org.apache.skywalking.banyandb.trace.v1.TraceServiceGrpc; -import org.apache.skywalking.banyandb.v1.client.BanyanDBClient; -import org.apache.skywalking.banyandb.v1.client.Options; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; -import org.apache.skywalking.banyandb.v1.client.util.StatusUtil; +import org.apache.skywalking.library.banyandb.v1.client.BanyanDBClient; +import org.apache.skywalking.library.banyandb.v1.client.Options; +import org.apache.skywalking.library.banyandb.v1.client.util.StatusUtil; import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics; /** @@ -74,8 +71,6 @@ public TraceBulkWriteProcessor( protected StreamObserver buildStreamObserver(TraceServiceGrpc.TraceServiceStub stub, CompletableFuture batch) { return stub.write( new StreamObserver() { - private final Set schemaExpired = new HashSet<>(); - @Override public void onNext(BanyandbTrace.WriteResponse writeResponse) { BanyandbModel.Status status = StatusUtil.convertStringToStatus(writeResponse.getStatus()); @@ -85,15 +80,7 @@ public void onNext(BanyandbTrace.WriteResponse writeResponse) { case STATUS_EXPIRED_SCHEMA: BanyandbCommon.Metadata metadata = writeResponse.getMetadata(); String schemaKey = metadata.getGroup() + "." + metadata.getName(); - if (!schemaExpired.contains(schemaKey)) { - log.warn("The trace schema {} is expired, trying update the schema...", schemaKey); - try { - client.updateTraceMetadataCacheFromServer(metadata.getGroup(), metadata.getName()); - schemaExpired.add(schemaKey); - } catch (BanyanDBException e) { - log.error(e.getMessage(), e); - } - } + log.error("The trace schema {} is expired", schemaKey); break; default: log.warn("Write trace failed with status: {}", status); diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBEBPFProfilingScheduleQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBEBPFProfilingScheduleQueryDAO.java index 09c13b014f36..651e45c2675b 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBEBPFProfilingScheduleQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBEBPFProfilingScheduleQueryDAO.java @@ -20,10 +20,10 @@ import com.google.common.collect.ImmutableSet; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingScheduleRecord; import org.apache.skywalking.oap.server.core.query.type.EBPFProfilingSchedule; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBHierarchyQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBHierarchyQueryDAO.java index 427b7801da6c..10d8a8b31761 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBHierarchyQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBHierarchyQueryDAO.java @@ -24,10 +24,10 @@ import java.util.Collections; import java.util.List; import java.util.Set; -import org.apache.skywalking.banyandb.v1.client.AbstractCriteria; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractCriteria; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.Layer; import org.apache.skywalking.oap.server.core.hierarchy.instance.InstanceHierarchyRelationTraffic; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureInsertRequest.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureInsertRequest.java index bbfe88337205..c91da31ceec3 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureInsertRequest.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureInsertRequest.java @@ -20,7 +20,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.apache.skywalking.banyandb.v1.client.MeasureWrite; +import org.apache.skywalking.library.banyandb.v1.client.MeasureWrite; import org.apache.skywalking.oap.server.core.storage.SessionCacheCallback; import org.apache.skywalking.oap.server.library.client.request.InsertRequest; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureUpdateRequest.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureUpdateRequest.java index 763537a03474..212e3ed0acae 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureUpdateRequest.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMeasureUpdateRequest.java @@ -20,7 +20,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.apache.skywalking.banyandb.v1.client.MeasureWrite; +import org.apache.skywalking.library.banyandb.v1.client.MeasureWrite; import org.apache.skywalking.oap.server.core.UnexpectedException; import org.apache.skywalking.oap.server.library.client.request.UpdateRequest; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java index 5f7cd9fc25cb..50a6fb08c699 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java @@ -24,11 +24,11 @@ import com.google.gson.JsonObject; import org.apache.commons.lang3.StringUtils; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.IDManager; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsDAO.java index ef8f86c6bb8c..4f1ff1928e88 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsDAO.java @@ -21,11 +21,11 @@ import com.google.common.base.Preconditions; import lombok.extern.slf4j.Slf4j; import org.apache.logging.log4j.util.Strings; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.MeasureWrite; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.MeasureWrite; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics; import org.apache.skywalking.oap.server.core.storage.IMetricsDAO; @@ -122,7 +122,7 @@ public List multiGet(Model model, List metrics) throws IOExcep } List metricsInStorage = new ArrayList<>(metrics.size()); - MeasureQueryResponse resp = query(false, schema, schema.getTags(), schema.getFields(), timestampRange, new QueryBuilder() { + MeasureQueryResponse resp = query(false, schema, schema.getTags().keySet(), schema.getFields(), timestampRange, new QueryBuilder() { @Override protected void apply(MeasureQuery query) { seriesIDColumns.entrySet().forEach(entry -> { diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java index 84b84290ca6a..a6d384b10ba9 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetricsQueryDAO.java @@ -26,9 +26,9 @@ import java.util.List; import java.util.Map; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable; import org.apache.skywalking.oap.server.core.analysis.metrics.HistogramMetrics; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBNetworkAddressAliasDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBNetworkAddressAliasDAO.java index 8b4055658f95..8d34767144b9 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBNetworkAddressAliasDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBNetworkAddressAliasDAO.java @@ -27,8 +27,8 @@ import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.manual.networkalias.NetworkAddressAlias; import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBServiceLabelDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBServiceLabelDAO.java index 64ed99f8b54b..bf73fafcf94c 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBServiceLabelDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBServiceLabelDAO.java @@ -26,7 +26,7 @@ import java.util.Set; import java.util.stream.Collectors; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.manual.process.ServiceLabelRecord; import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IServiceLabelDAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTagAutocompleteQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTagAutocompleteQueryDAO.java index 9ae3985f770e..53c23a3b7805 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTagAutocompleteQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTagAutocompleteQueryDAO.java @@ -19,10 +19,10 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.measure; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.TagAutocompleteData; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java index d6d9099f2ee8..3204c0da0738 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBTopologyQueryDAO.java @@ -28,10 +28,10 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; -import org.apache.skywalking.banyandb.v1.client.AbstractCriteria; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractCriteria; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; import org.apache.skywalking.oap.server.core.UnexpectedException; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.manual.relation.endpoint.EndpointRelationServerSideMetrics; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/AbstractBanyanDBDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/AbstractBanyanDBDAO.java index c5a23b35e2ce..144cbe609bf5 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/AbstractBanyanDBDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/AbstractBanyanDBDAO.java @@ -20,24 +20,26 @@ import com.google.gson.Gson; import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; import javax.annotation.Nullable; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.AbstractCriteria; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.And; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.Or; -import org.apache.skywalking.banyandb.v1.client.PairQueryCondition; -import org.apache.skywalking.banyandb.v1.client.Span; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; -import org.apache.skywalking.banyandb.v1.client.TopNQuery; -import org.apache.skywalking.banyandb.v1.client.TopNQueryResponse; -import org.apache.skywalking.banyandb.v1.client.Trace; -import org.apache.skywalking.banyandb.v1.client.TraceQuery; -import org.apache.skywalking.banyandb.v1.client.TraceQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractCriteria; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.And; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.Or; +import org.apache.skywalking.library.banyandb.v1.client.PairQueryCondition; +import org.apache.skywalking.library.banyandb.v1.client.Span; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.TopNQuery; +import org.apache.skywalking.library.banyandb.v1.client.TopNQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.Trace; +import org.apache.skywalking.library.banyandb.v1.client.TraceQuery; +import org.apache.skywalking.library.banyandb.v1.client.TraceQueryResponse; import org.apache.skywalking.oap.server.core.query.input.AttrCondition; import org.apache.skywalking.oap.server.core.query.input.Duration; import org.apache.skywalking.oap.server.core.query.type.KeyValue; @@ -85,10 +87,14 @@ protected StreamQueryResponse query(boolean isColdStage, throw new IllegalArgumentException("schema is not registered"); } final StreamQuery query; + Map tagProjections = tags.stream().collect(Collectors.toMap( + tagName -> tagName, + tagName -> schema.getTags().get(tagName) + )); if (timestampRange == null) { - query = new StreamQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), LARGEST_TIME_RANGE, tags); + query = new StreamQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), LARGEST_TIME_RANGE, tagProjections); } else { - query = new StreamQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), timestampRange, tags); + query = new StreamQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), timestampRange, tagProjections); } if (isColdStage) { query.setStages(Set.of(BanyanDBStorageConfig.StageName.cold.name())); @@ -280,10 +286,14 @@ protected MeasureQueryResponse query(boolean isColdStage, throw new IllegalArgumentException("measure is not registered"); } final MeasureQuery query; + Map tagProjections = tags.stream().collect(Collectors.toMap( + tagName -> tagName, + tagName -> schema.getTags().get(tagName) + )); if (timestampRange == null) { - query = new MeasureQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), LARGEST_TIME_RANGE, tags, fields); + query = new MeasureQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), LARGEST_TIME_RANGE, tagProjections, fields); } else { - query = new MeasureQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), timestampRange, tags, fields); + query = new MeasureQuery(List.of(schema.getMetadata().getGroup()), schema.getMetadata().name(), timestampRange, tagProjections, fields); } if (isColdStage) { query.setStages(Set.of(BanyanDBStorageConfig.StageName.cold.name())); diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAlarmQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAlarmQueryDAO.java index 799f497d2339..ca5f8628f82a 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAlarmQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAlarmQueryDAO.java @@ -19,10 +19,10 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.alarm.AlarmRecord; import org.apache.skywalking.oap.server.core.alarm.AlarmRecoveryRecord; import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskLogQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskLogQueryDAO.java index 8fcf708db1cf..68e783cb45d1 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskLogQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskLogQueryDAO.java @@ -19,9 +19,9 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.Element; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.Element; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.profiling.asyncprofiler.storage.AsyncProfilerTaskLogRecord; import org.apache.skywalking.oap.server.core.query.AsyncProfilerTaskLog; import org.apache.skywalking.oap.server.core.query.type.AsyncProfilerTaskLogOperationType; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskQueryDAO.java index aaf9d453b1d2..c8155ed98b28 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBAsyncProfilerTaskQueryDAO.java @@ -21,11 +21,11 @@ import com.google.common.collect.ImmutableSet; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; import org.apache.skywalking.oap.server.core.profiling.asyncprofiler.storage.AsyncProfilerTaskRecord; import org.apache.skywalking.oap.server.core.query.type.AsyncProfilerEventType; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBBrowserLogQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBBrowserLogQueryDAO.java index 4e5582486189..3e1c5838d541 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBBrowserLogQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBBrowserLogQueryDAO.java @@ -19,9 +19,9 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.browser.manual.errorlog.BrowserErrorLogRecord; import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory; import org.apache.skywalking.oap.server.core.query.input.Duration; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBContinuousProfilingPolicyDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBContinuousProfilingPolicyDAO.java index 2de1740b9eb0..1f43741cbb52 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBContinuousProfilingPolicyDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBContinuousProfilingPolicyDAO.java @@ -21,7 +21,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.TagAndValue; +import org.apache.skywalking.library.banyandb.v1.client.TagAndValue; import org.apache.skywalking.banyandb.property.v1.BanyandbProperty.Property; import org.apache.skywalking.oap.server.core.profiling.continuous.storage.ContinuousProfilingPolicy; import org.apache.skywalking.oap.server.core.storage.profiling.continuous.IContinuousProfilingPolicyDAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingDataDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingDataDAO.java index 19d8717fc872..e840ec466de3 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingDataDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingDataDAO.java @@ -19,9 +19,9 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingDataRecord; import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingDataDAO; import org.apache.skywalking.oap.server.storage.plugin.banyandb.BanyanDBConverter; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingTaskDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingTaskDAO.java index d601ffb1ce3b..a585223a76b8 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingTaskDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEBPFProfilingTaskDAO.java @@ -19,10 +19,10 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTargetType; import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTaskRecord; import org.apache.skywalking.oap.server.core.profiling.ebpf.storage.EBPFProfilingTriggerType; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEventQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEventQueryDAO.java index 7b53aea70d5c..14330aee9050 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEventQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBEventQueryDAO.java @@ -24,12 +24,12 @@ import java.util.Set; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.AbstractCriteria; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.Element; -import org.apache.skywalking.banyandb.v1.client.PairQueryCondition; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractCriteria; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.Element; +import org.apache.skywalking.library.banyandb.v1.client.PairQueryCondition; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.analysis.Layer; import org.apache.skywalking.oap.server.core.query.PaginationUtils; import org.apache.skywalking.oap.server.core.query.enumeration.Order; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBJFRDataQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBJFRDataQueryDAO.java index d54cc5a29339..c8f35dac78c2 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBJFRDataQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBJFRDataQueryDAO.java @@ -19,9 +19,9 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.profiling.asyncprofiler.storage.JFRProfilingDataRecord; import org.apache.skywalking.oap.server.core.storage.profiling.asyncprofiler.IJFRDataQueryDAO; import org.apache.skywalking.oap.server.library.util.CollectionUtils; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBLogQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBLogQueryDAO.java index cc3b0f4ec1e1..7acc097f80f8 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBLogQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBLogQueryDAO.java @@ -19,10 +19,10 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.analysis.IDManager; import org.apache.skywalking.oap.server.core.analysis.manual.log.AbstractLogRecord; import org.apache.skywalking.oap.server.core.analysis.manual.log.LogRecord; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofDataQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofDataQueryDAO.java index 3cd01466165c..817199400ccf 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofDataQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofDataQueryDAO.java @@ -23,9 +23,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.profiling.pprof.storage.PprofProfilingDataRecord; import org.apache.skywalking.oap.server.core.storage.profiling.pprof.IPprofDataQueryDAO; import org.apache.skywalking.oap.server.library.util.CollectionUtils; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskLogQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskLogQueryDAO.java index 0f82af2f267c..38b133d64935 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskLogQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskLogQueryDAO.java @@ -23,9 +23,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; -import org.apache.skywalking.banyandb.v1.client.Element; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.Element; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.profiling.pprof.storage.PprofTaskLogRecord; import org.apache.skywalking.oap.server.core.query.PprofTaskLog; import org.apache.skywalking.oap.server.core.query.type.PprofTaskLogOperationType; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskQueryDAO.java index 6a2332faa345..97274742b6d4 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBPprofTaskQueryDAO.java @@ -27,11 +27,11 @@ import java.util.List; import java.util.Set; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; import org.apache.skywalking.oap.server.core.profiling.pprof.storage.PprofTaskRecord; import org.apache.skywalking.oap.server.core.query.type.PprofEventType; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskLogQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskLogQueryDAO.java index 420c0b5b99d7..c8287d62188c 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskLogQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskLogQueryDAO.java @@ -19,9 +19,9 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.Element; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.Element; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.profiling.trace.ProfileTaskLogRecord; import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLog; import org.apache.skywalking.oap.server.core.query.type.ProfileTaskLogOperationType; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskQueryDAO.java index 040db07a5e62..2c119ab9c657 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileTaskQueryDAO.java @@ -19,11 +19,11 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.analysis.TimeBucket; import org.apache.skywalking.oap.server.core.profiling.trace.ProfileTaskRecord; import org.apache.skywalking.oap.server.core.query.type.ProfileTask; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileThreadSnapshotQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileThreadSnapshotQueryDAO.java index 4c9609f52b88..491bf2b6154d 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileThreadSnapshotQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBProfileThreadSnapshotQueryDAO.java @@ -19,11 +19,11 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; import com.google.common.collect.ImmutableSet; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord; import org.apache.skywalking.oap.server.core.profiling.trace.ProfileThreadSnapshotRecord; import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileThreadSnapshotQueryDAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBRecordDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBRecordDAO.java index 94a16ec420a1..8bb0d28f8009 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBRecordDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBRecordDAO.java @@ -18,11 +18,12 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb.stream; +import java.util.Map; import lombok.extern.slf4j.Slf4j; -import org.apache.skywalking.banyandb.v1.client.StreamWrite; -import org.apache.skywalking.banyandb.v1.client.TagAndValue; -import org.apache.skywalking.banyandb.v1.client.TraceWrite; -import org.apache.skywalking.banyandb.v1.client.grpc.exception.BanyanDBException; +import org.apache.skywalking.library.banyandb.v1.client.StreamWrite; +import org.apache.skywalking.library.banyandb.v1.client.TagAndValue; +import org.apache.skywalking.library.banyandb.v1.client.TraceWrite; +import org.apache.skywalking.library.banyandb.v1.client.grpc.exception.BanyanDBException; import org.apache.skywalking.oap.server.core.storage.model.BanyanDBTrace; import org.apache.skywalking.oap.server.core.analysis.record.Record; import org.apache.skywalking.oap.server.core.storage.IRecordDAO; @@ -65,7 +66,8 @@ public InsertRequest prepareBatchInsert(Model model, Record record) throws IOExc mergeTable.getMergeTableName() ); try { - for (String tag : mergeTableSchema.getTags()) { + for (Map.Entry entry : mergeTableSchema.getTags().entrySet()) { + String tag = entry.getKey(); if (tag.equals(mergeTable.getMergeTraceIdColumnName())) { traceWrite.tag( tag, diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBSpanAttachedEventQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBSpanAttachedEventQueryDAO.java index 2a8e4aa671ff..43c8a6460065 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBSpanAttachedEventQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBSpanAttachedEventQueryDAO.java @@ -20,10 +20,10 @@ import com.google.common.collect.ImmutableSet; import javax.annotation.Nullable; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.RowEntity; -import org.apache.skywalking.banyandb.v1.client.StreamQuery; -import org.apache.skywalking.banyandb.v1.client.StreamQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.RowEntity; +import org.apache.skywalking.library.banyandb.v1.client.StreamQuery; +import org.apache.skywalking.library.banyandb.v1.client.StreamQueryResponse; import org.apache.skywalking.oap.server.core.analysis.manual.spanattach.SWSpanAttachedEventRecord; import org.apache.skywalking.oap.server.core.analysis.manual.spanattach.SpanAttachedEventRecord; import org.apache.skywalking.oap.server.core.query.input.Duration; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBStreamInsertRequest.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBStreamInsertRequest.java index 15dbc52c53de..e4e83b53d622 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBStreamInsertRequest.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/stream/BanyanDBStreamInsertRequest.java @@ -20,7 +20,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.apache.skywalking.banyandb.v1.client.StreamWrite; +import org.apache.skywalking.library.banyandb.v1.client.StreamWrite; import org.apache.skywalking.oap.server.library.client.request.InsertRequest; @RequiredArgsConstructor diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceInsertRequest.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceInsertRequest.java index dbef0e00681e..015facfdc00c 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceInsertRequest.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceInsertRequest.java @@ -20,7 +20,7 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; -import org.apache.skywalking.banyandb.v1.client.TraceWrite; +import org.apache.skywalking.library.banyandb.v1.client.TraceWrite; import org.apache.skywalking.oap.server.library.client.request.InsertRequest; @RequiredArgsConstructor diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceQueryDAO.java index a8699653ad71..2f02c4918ca0 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBTraceQueryDAO.java @@ -22,10 +22,10 @@ import org.apache.skywalking.apm.network.language.agent.v3.SegmentObject; import org.apache.skywalking.apm.network.language.agent.v3.SpanObject; import org.apache.skywalking.apm.network.language.agent.v3.SpanType; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; -import org.apache.skywalking.banyandb.v1.client.TraceQuery; -import org.apache.skywalking.banyandb.v1.client.TraceQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.TraceQuery; +import org.apache.skywalking.library.banyandb.v1.client.TraceQueryResponse; import org.apache.skywalking.oap.server.core.Const; import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.analysis.IDManager; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBZipkinQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBZipkinQueryDAO.java index 3908401f7c10..be1a5c16f3c5 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBZipkinQueryDAO.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/trace/BanyanDBZipkinQueryDAO.java @@ -26,12 +26,12 @@ import java.util.Map; import java.util.Set; import javax.annotation.Nullable; -import org.apache.skywalking.banyandb.v1.client.AbstractQuery; -import org.apache.skywalking.banyandb.v1.client.DataPoint; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.TraceQuery; -import org.apache.skywalking.banyandb.v1.client.TraceQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.AbstractQuery; +import org.apache.skywalking.library.banyandb.v1.client.DataPoint; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.TraceQuery; +import org.apache.skywalking.library.banyandb.v1.client.TraceQueryResponse; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.query.input.Duration; import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryV2DAO; diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIT.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIT.java index 8eedfd693e95..8539e4c52e4c 100644 --- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIT.java +++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/test/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/BanyanDBIT.java @@ -18,6 +18,7 @@ package org.apache.skywalking.oap.server.storage.plugin.banyandb; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import java.time.Instant; @@ -29,11 +30,11 @@ import org.apache.skywalking.banyandb.common.v1.BanyandbCommon; import org.apache.skywalking.banyandb.database.v1.BanyandbDatabase; import org.apache.skywalking.banyandb.model.v1.BanyandbModel; -import org.apache.skywalking.banyandb.v1.client.MeasureQuery; -import org.apache.skywalking.banyandb.v1.client.MeasureQueryResponse; -import org.apache.skywalking.banyandb.v1.client.MeasureWrite; -import org.apache.skywalking.banyandb.v1.client.TagAndValue; -import org.apache.skywalking.banyandb.v1.client.TimestampRange; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQuery; +import org.apache.skywalking.library.banyandb.v1.client.MeasureQueryResponse; +import org.apache.skywalking.library.banyandb.v1.client.MeasureWrite; +import org.apache.skywalking.library.banyandb.v1.client.TagAndValue; +import org.apache.skywalking.library.banyandb.v1.client.TimestampRange; import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.analysis.DownSampling; import org.apache.skywalking.oap.server.core.analysis.Stream; @@ -165,11 +166,11 @@ public void testInstall() throws Exception { installer.createTable(model); //test Measure install BanyandbDatabase.Measure measure = client.client.findMeasure(groupName, "testMetric_minute"); - assertEquals("default", measure.getTagFamilies(0).getName()); - assertEquals("tag", measure.getTagFamilies(0).getTags(0).getName()); + assertEquals("storage-only", measure.getTagFamilies(0).getName()); + assertEquals("service_id", measure.getTagFamilies(0).getTags(0).getName()); assertEquals(BanyandbDatabase.TagType.TAG_TYPE_STRING, measure.getTagFamilies(0).getTags(0).getType()); - assertEquals("storage-only", measure.getTagFamilies(1).getName()); - assertEquals("service_id", measure.getTagFamilies(1).getTags(0).getName()); + assertEquals("searchable", measure.getTagFamilies(1).getName()); + assertEquals("tag", measure.getTagFamilies(1).getTags(0).getName()); assertEquals(BanyandbDatabase.TagType.TAG_TYPE_STRING, measure.getTagFamilies(1).getTags(0).getType()); assertEquals("service_id", measure.getEntity().getTagNames(0)); assertEquals("value", measure.getFields(0).getName()); @@ -195,8 +196,8 @@ public void testInstall() throws Exception { Instant now = Instant.now(); Instant begin = now.minus(15, ChronoUnit.MINUTES); MeasureWrite measureWrite = client.createMeasureWrite(groupName, "testMetric_minute", now.toEpochMilli()); - measureWrite.tag("service_id", TagAndValue.stringTagValue("service1")) - .tag("tag", TagAndValue.stringTagValue("tag1")) + measureWrite.tag("storage-only", "service_id", TagAndValue.stringTagValue("service1")) + .tag("searchable", "tag", TagAndValue.stringTagValue("tag1")) .field("value", TagAndValue.longFieldValue(100)); CompletableFuture f = processor.add(measureWrite); f.exceptionally(exp -> { @@ -209,7 +210,7 @@ public void testInstall() throws Exception { new TimestampRange( begin.toEpochMilli(), now.plus(1, ChronoUnit.MINUTES).toEpochMilli() - ), ImmutableSet.of("service_id", "tag"), + ), ImmutableMap.of("service_id", "storage-only", "tag", "searchable"), ImmutableSet.of("value") ); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { @@ -236,14 +237,14 @@ public void testInstall() throws Exception { assertEquals(updatedGroup.getResourceOpts().getTtl().getNum(), 10); //test Measure update BanyandbDatabase.Measure updatedMeasure = client.client.findMeasure(groupName, "testMetric_minute"); - assertEquals("default", updatedMeasure.getTagFamilies(0).getName()); - assertEquals("tag", updatedMeasure.getTagFamilies(0).getTags(0).getName()); - assertEquals("new_tag", updatedMeasure.getTagFamilies(0).getTags(1).getName()); + assertEquals("storage-only", updatedMeasure.getTagFamilies(0).getName()); + assertEquals("service_id", updatedMeasure.getTagFamilies(0).getTags(0).getName()); assertEquals(BanyandbDatabase.TagType.TAG_TYPE_STRING, updatedMeasure.getTagFamilies(0).getTags(0).getType()); - assertEquals(BanyandbDatabase.TagType.TAG_TYPE_STRING, updatedMeasure.getTagFamilies(0).getTags(1).getType()); - assertEquals("storage-only", updatedMeasure.getTagFamilies(1).getName()); - assertEquals("service_id", updatedMeasure.getTagFamilies(1).getTags(0).getName()); + assertEquals("searchable", updatedMeasure.getTagFamilies(1).getName()); + assertEquals("tag", updatedMeasure.getTagFamilies(1).getTags(0).getName()); + assertEquals("new_tag", updatedMeasure.getTagFamilies(1).getTags(1).getName()); assertEquals(BanyandbDatabase.TagType.TAG_TYPE_STRING, updatedMeasure.getTagFamilies(1).getTags(0).getType()); + assertEquals(BanyandbDatabase.TagType.TAG_TYPE_STRING, updatedMeasure.getTagFamilies(1).getTags(1).getType()); assertEquals("service_id", updatedMeasure.getEntity().getTagNames(0)); assertEquals("value", updatedMeasure.getFields(0).getName()); assertEquals(BanyandbDatabase.FieldType.FIELD_TYPE_INT, updatedMeasure.getFields(0).getFieldType()); @@ -262,11 +263,10 @@ public void testInstall() throws Exception { assertEquals("new_tag", updatedIndexRuleBinding.getRules(1)); assertEquals("testMetric_minute", updatedIndexRuleBinding.getSubject().getName()); //test data - client.client.updateMeasureMetadataCacheFromSever(groupName, "testMetric_minute"); MeasureWrite updatedMeasureWrite = client.createMeasureWrite(groupName, "testMetric_minute", now.plus(10, ChronoUnit.MINUTES).toEpochMilli()); - updatedMeasureWrite.tag("service_id", TagAndValue.stringTagValue("service2")) - .tag("tag", TagAndValue.stringTagValue("tag1")) - .tag("new_tag", TagAndValue.stringTagValue("new_tag1")) + updatedMeasureWrite.tag("storage-only", "service_id", TagAndValue.stringTagValue("service2")) + .tag("searchable", "tag", TagAndValue.stringTagValue("tag1")) + .tag("searchable", "new_tag", TagAndValue.stringTagValue("new_tag1")) .field("value", TagAndValue.longFieldValue(101)) .field("new_value", TagAndValue.longFieldValue(1000)); CompletableFuture cf = processor.add(updatedMeasureWrite); @@ -275,12 +275,11 @@ public void testInstall() throws Exception { return null; }); cf.get(10, TimeUnit.SECONDS); - MeasureQuery updatedQuery = new MeasureQuery(Lists.newArrayList(groupName), "testMetric_minute", - new TimestampRange( - begin.toEpochMilli(), - now.plus(15, ChronoUnit.MINUTES).toEpochMilli() - ), ImmutableSet.of("service_id", "tag", "new_tag"), - ImmutableSet.of("value", "new_value") + MeasureQuery updatedQuery = new MeasureQuery( + Lists.newArrayList(groupName), "testMetric_minute", + new TimestampRange(begin.toEpochMilli(), now.plus(15, ChronoUnit.MINUTES).toEpochMilli()), + ImmutableMap.of("service_id", "storage-only", "tag", "searchable", "new_tag", "searchable"), + ImmutableSet.of("value", "new_value") ); await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> { MeasureQueryResponse updatedResp = client.query(updatedQuery); diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java index 221062944e2d..bb0518d99535 100644 --- a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java +++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileSnapshotExporterTest.java @@ -29,6 +29,7 @@ import org.apache.skywalking.oap.server.core.query.input.SegmentProfileAnalyzeQuery; import org.apache.skywalking.oap.server.core.query.type.ProfileAnalyzeTimeRange; import org.apache.skywalking.oap.server.core.storage.StorageModule; +import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileTaskQueryDAO; import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileThreadSnapshotQueryDAO; import org.apache.skywalking.oap.server.core.storage.query.ISpanAttachedEventQueryDAO; import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO; @@ -87,6 +88,7 @@ public void init() throws IOException { .thenReturn(new ProfileExportSnapshotDAO(exportedData)); Mockito.when(moduleProvider.getService(ITraceQueryDAO.class)).thenReturn(new ProfileTraceDAO(exportedData)); Mockito.when(moduleProvider.getService(ISpanAttachedEventQueryDAO.class)).thenReturn(new SpanAttachedEventQueryDAO()); + Mockito.when(moduleProvider.getService(IProfileTaskQueryDAO.class)).thenReturn(new ProfileTaskQueryDAO()); } @Test diff --git a/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTaskQueryDAO.java b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTaskQueryDAO.java new file mode 100644 index 000000000000..49926f03774c --- /dev/null +++ b/oap-server/server-tools/profile-exporter/tool-profile-snapshot-bootstrap/src/test/java/org/apache/skywalking/oap/server/tool/profile/exporter/test/ProfileTaskQueryDAO.java @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.oap.server.tool.profile.exporter.test; + +import java.io.IOException; +import java.util.List; +import org.apache.skywalking.oap.server.core.query.type.ProfileTask; +import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileTaskQueryDAO; + +public class ProfileTaskQueryDAO implements IProfileTaskQueryDAO { + @Override + public List getTaskList(final String serviceId, + final String endpointName, + final Long startTimeBucket, + final Long endTimeBucket, + final Integer limit) throws IOException { + return List.of(); + } + + @Override + public ProfileTask getById(final String id) throws IOException { + return new ProfileTask(); + } +} diff --git a/pom.xml b/pom.xml index 46037ba17b17..b75ae2c9b433 100755 --- a/pom.xml +++ b/pom.xml @@ -173,6 +173,7 @@ 0.6.1 3.19.2 1.42.1 + 1.2.1 1.3.2 3.1 @@ -405,6 +406,10 @@ ${skipUTs} ${argLine} + + **/IT*.java + **/*IT.java + diff --git a/test/e2e-v2/script/env b/test/e2e-v2/script/env index 3fa61bc3d1c2..43eaf1247c29 100644 --- a/test/e2e-v2/script/env +++ b/test/e2e-v2/script/env @@ -23,7 +23,7 @@ SW_AGENT_CLIENT_JS_COMMIT=f08776d909eb1d9bc79c600e493030651b97e491 SW_AGENT_CLIENT_JS_TEST_COMMIT=4f1eb1dcdbde3ec4a38534bf01dded4ab5d2f016 SW_KUBERNETES_COMMIT_SHA=6fe5e6f0d3b7686c6be0457733e825ee68cb9b35 SW_ROVER_COMMIT=79292fe07f17f98f486e0c4471213e1961fb2d1d -SW_BANYANDB_COMMIT=7466afd2a2120f7fa311983be5a3077cb15d07e7 +SW_BANYANDB_COMMIT=a69048c4ff85f437002edacf83918c8f8ba5951a SW_AGENT_PHP_COMMIT=d1114e7be5d89881eec76e5b56e69ff844691e35 SW_PREDICTOR_COMMIT=54a0197654a3781a6f73ce35146c712af297c994