Copilot commented on code in PR #13655:
URL: https://github.com/apache/skywalking/pull/13655#discussion_r2666793152


##########
oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClient.java:
##########
@@ -0,0 +1,1113 @@
+/*
+ * 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 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.
+ *
+ * <pre>{@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();
+ * }</pre>
+ */
+@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 (!"".equals(username) && !"".equals(password)) {

Review Comment:
   Inefficient comparison to empty string, check for zero length instead.
   ```suggestion
                   if (username != null && !username.isEmpty()
                           && password != null && !password.isEmpty()) {
   ```



##########
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)

Review Comment:
   This method overrides [Value<T>.canEqual](1); it is advisable to add an 
Override annotation.



##########
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("(((?<day>\\d+)d)?((?<hour>\\d+)h)?((?<minute>\\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);

Review Comment:
   Potential uncaught 'java.lang.NumberFormatException'.



##########
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<T> extends Value<T> {
+    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<String> {
+        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<String> newStringTag(final String tagName, final 
String value) {
+        return new StringTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)

Review Comment:
   This method overrides [TagAndValue<List<String>>.canEqual](1); it is 
advisable to add an Override annotation.



##########
oap-server/server-library/library-banyandb-client/src/main/java/org/apache/skywalking/library/banyandb/v1/client/BanyanDBClient.java:
##########
@@ -0,0 +1,1113 @@
+/*
+ * 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 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.
+ *
+ * <pre>{@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();
+ * }</pre>
+ */
+@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 (!"".equals(username) && !"".equals(password)) {

Review Comment:
   Inefficient comparison to empty string, check for zero length instead.
   ```suggestion
                   if (!Strings.isNullOrEmpty(username) && 
!Strings.isNullOrEmpty(password)) {
   ```



##########
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("(((?<day>\\d+)d)?((?<hour>\\d+)h)?((?<minute>\\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;

Review Comment:
   Potential uncaught 'java.lang.NumberFormatException'.



##########
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<T> extends Value<T> {
+    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)

Review Comment:
   This method overrides [TagAndValue<String>.canEqual](1); it is advisable to 
add an Override annotation.



##########
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("(((?<day>\\d+)d)?((?<hour>\\d+)h)?((?<minute>\\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;

Review Comment:
   Potential uncaught 'java.lang.NumberFormatException'.



##########
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<T> extends Value<T> {
+    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<String> {
+        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<String> newStringTag(final String tagName, final 
String value) {
+        return new StringTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class StringArrayTagPair extends TagAndValue<List<String>> {
+        StringArrayTagPair(final String tagName, final List<String> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setStrArray(BanyandbModel.StrArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<List<String>> newStringArrayTagPair(final String 
tagName, final List<String> value) {
+        return new StringArrayTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class LongTagPair extends TagAndValue<Long> {
+        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<Long> newLongTag(final String tagName, final 
long value) {
+        return new LongTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)

Review Comment:
   This method overrides [TagAndValue<List<Long>>.canEqual](1); it is advisable 
to add an Override annotation.



##########
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<T> extends Value<T> {
+    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<String> {
+        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<String> newStringTag(final String tagName, final 
String value) {
+        return new StringTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class StringArrayTagPair extends TagAndValue<List<String>> {
+        StringArrayTagPair(final String tagName, final List<String> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setStrArray(BanyandbModel.StrArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<List<String>> newStringArrayTagPair(final String 
tagName, final List<String> value) {
+        return new StringArrayTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class LongTagPair extends TagAndValue<Long> {
+        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<Long> newLongTag(final String tagName, final 
long value) {
+        return new LongTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class LongArrayTagPair extends TagAndValue<List<Long>> {
+        LongArrayTagPair(final String tagName, final List<Long> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setIntArray(BanyandbModel.IntArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<Long> newLongArrayTag(final String tagName, 
final long value) {
+        return new LongTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class BinaryTagPair extends TagAndValue<ByteString> {
+        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<ByteString> newBinaryTag(final String tagName, 
final byte[] bytes) {
+        return new BinaryTagPair(tagName, ByteString.copyFrom(bytes));
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class TimestampTagPair extends TagAndValue<Long> {
+        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<Long> newTimestampTag(final String tagName, 
final long epochMilli) {
+        return new TimestampTagPair(tagName, epochMilli);
+    }
+
+    @EqualsAndHashCode(callSuper = true)

Review Comment:
   This method overrides [TagAndValue<Void>.canEqual](1); it is advisable to 
add an Override annotation.



##########
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<T> extends Value<T> {
+    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<String> {
+        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<String> newStringTag(final String tagName, final 
String value) {
+        return new StringTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class StringArrayTagPair extends TagAndValue<List<String>> {
+        StringArrayTagPair(final String tagName, final List<String> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setStrArray(BanyandbModel.StrArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<List<String>> newStringArrayTagPair(final String 
tagName, final List<String> value) {
+        return new StringArrayTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class LongTagPair extends TagAndValue<Long> {
+        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<Long> newLongTag(final String tagName, final 
long value) {
+        return new LongTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class LongArrayTagPair extends TagAndValue<List<Long>> {
+        LongArrayTagPair(final String tagName, final List<Long> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setIntArray(BanyandbModel.IntArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<Long> newLongArrayTag(final String tagName, 
final long value) {
+        return new LongTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)

Review Comment:
   This method overrides [TagAndValue<ByteString>.canEqual](1); it is advisable 
to add an Override annotation.



##########
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<T> extends Value<T> {
+    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<String> {
+        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<String> newStringTag(final String tagName, final 
String value) {
+        return new StringTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class StringArrayTagPair extends TagAndValue<List<String>> {
+        StringArrayTagPair(final String tagName, final List<String> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setStrArray(BanyandbModel.StrArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<List<String>> newStringArrayTagPair(final String 
tagName, final List<String> value) {
+        return new StringArrayTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class LongTagPair extends TagAndValue<Long> {
+        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<Long> newLongTag(final String tagName, final 
long value) {
+        return new LongTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class LongArrayTagPair extends TagAndValue<List<Long>> {
+        LongArrayTagPair(final String tagName, final List<Long> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setIntArray(BanyandbModel.IntArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<Long> newLongArrayTag(final String tagName, 
final long value) {
+        return new LongTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class BinaryTagPair extends TagAndValue<ByteString> {
+        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<ByteString> newBinaryTag(final String tagName, 
final byte[] bytes) {
+        return new BinaryTagPair(tagName, ByteString.copyFrom(bytes));
+    }
+
+    @EqualsAndHashCode(callSuper = true)

Review Comment:
   This method overrides [TagAndValue<Long>.canEqual](1); it is advisable to 
add an Override annotation.



##########
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<T> extends Value<T> {
+    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<String> {
+        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<String> newStringTag(final String tagName, final 
String value) {
+        return new StringTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)
+    public static class StringArrayTagPair extends TagAndValue<List<String>> {
+        StringArrayTagPair(final String tagName, final List<String> value) {
+            super(tagName, value);
+        }
+
+        @Override
+        protected BanyandbModel.TagValue buildTypedTagValue() {
+            return BanyandbModel.TagValue.newBuilder()
+                    .setStrArray(BanyandbModel.StrArray
+                            .newBuilder()
+                            .addAllValue(value).build())
+                    .build();
+        }
+    }
+
+    public static TagAndValue<List<String>> newStringArrayTagPair(final String 
tagName, final List<String> value) {
+        return new StringArrayTagPair(tagName, value);
+    }
+
+    @EqualsAndHashCode(callSuper = true)

Review Comment:
   This method overrides [TagAndValue<Long>.canEqual](1); it is advisable to 
add an Override annotation.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to