Skip to content

Commit

Permalink
[#10431] Optional gRPC stat logging in agent
Browse files Browse the repository at this point in the history
  • Loading branch information
youngjin.kim2 authored and smilu97 committed Oct 26, 2023
1 parent 5a1baf6 commit 091d898
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 13 deletions.
3 changes: 3 additions & 0 deletions agent/src/main/resources/pinpoint-root.config
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ profiler.transport.grpc.span.sender.maxtraceevent=8
profiler.transport.grpc.span.sender.limitcount=100
profiler.transport.grpc.span.sender.limittime=60000

profiler.transport.grpc.stats.logging.period=PT1M
profiler.transport.grpc.span.stats.logging.enabled=false

# Grpc Tls
profiler.transport.grpc.ssl.enable=false
# openssl or jdk (jdk requires 1.9 or above)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ public class DefaultProfilerConfig implements ProfilerConfig {
@Value("${profiler.jdbc.maxsqlbindvaluesize}")
private int maxSqlBindValueSize = 1024;

@Value("${profiler.transport.grpc.stats.logging.period}")
private String grpcStatLoggingPeriod = "PT1M";


private HttpStatusCodeErrors httpStatusCodeErrors = new HttpStatusCodeErrors();

Expand Down Expand Up @@ -128,6 +131,10 @@ public int getMaxSqlBindValueSize() {
return maxSqlBindValueSize;
}

@Override
public String getGrpcStatLoggingPeriod() {
return grpcStatLoggingPeriod;
}

@Override
public boolean getStaticResourceCleanup() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public interface ProfilerConfig {

int getMaxSqlBindValueSize();

String getGrpcStatLoggingPeriod();

@InterfaceAudience.Private
@VisibleForTesting
boolean getStaticResourceCleanup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ public class GrpcTransportConfig {
private static final int DEFAULT_METADATA_RETRY_DELAY_MILLIS = 1000;
public static final boolean DEFAULT_NETTY_SYSTEM_PROPERTY_TRY_REFLECTIVE_SET_ACCESSIBLE = true;

private static final boolean DEFAULT_ENABLE_SPAN_STATS_LOGGING = false;

private ClientOption agentClientOption = new ClientOption();
private ClientOption metadataClientOption = new ClientOption();
private ClientOption statClientOption = new ClientOption();
Expand Down Expand Up @@ -132,6 +134,8 @@ public class GrpcTransportConfig {
private int spanSenderExecutorQueueSize = DEFAULT_SPAN_SENDER_EXECUTOR_QUEUE_SIZE;
@Value("${profiler.transport.grpc.span.sender.channel.executor.queue.size}")
private int spanChannelExecutorQueueSize = DEFAULT_SPAN_CHANNEL_EXECUTOR_QUEUE_SIZE;
@Value("${profiler.transport.grpc.span.stats.logging.enable}")
private boolean spanEnableStatLogging = DEFAULT_ENABLE_SPAN_STATS_LOGGING;

@Value("${profiler.transport.grpc.span.sender.discardpolicy.logger.discard.ratelimit}")
private int spanDiscardLogRateLimit = DEFAULT_DISCARD_LOG_RATE_LIMIT;
Expand Down Expand Up @@ -365,6 +369,10 @@ public int getMetadataRetryDelayMillis() {
return metadataRetryDelayMillis;
}

public boolean isSpanEnableStatLogging() {
return spanEnableStatLogging;
}

public boolean isNettySystemPropertyTryReflectiveSetAccessible() {
return nettySystemPropertyTryReflectiveSetAccessible;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
import com.navercorp.pinpoint.profiler.sender.grpc.ReconnectExecutor;
import com.navercorp.pinpoint.profiler.sender.grpc.SubconnectionExpiringLoadBalancerProvider;
import com.navercorp.pinpoint.profiler.sender.grpc.metric.ChannelzScheduledReporter;
import com.navercorp.pinpoint.profiler.sender.grpc.metric.DefaultChannelzScheduledReporter;
import com.navercorp.pinpoint.profiler.sender.grpc.metric.ChannelzScheduledReporterBuilder;
import io.grpc.LoadBalancerRegistry;
import io.grpc.NameResolverProvider;
import io.netty.handler.ssl.SslContext;
Expand All @@ -74,10 +74,11 @@ public class GrpcModule extends PrivateModule {

private final ProfilerConfig profilerConfig;

private final ChannelzScheduledReporter reporter = new DefaultChannelzScheduledReporter();
private final ChannelzScheduledReporter reporter;

public GrpcModule(ProfilerConfig profilerConfig) {
this.profilerConfig = Objects.requireNonNull(profilerConfig, "profilerConfig");
this.reporter = new ChannelzScheduledReporterBuilder().acceptConfig(this.profilerConfig).build();
}

@Override
Expand All @@ -86,7 +87,7 @@ protected void configure() {
GrpcTransportConfig grpcTransportConfig = loadGrpcTransportConfig();
bind(GrpcTransportConfig.class).toInstance(grpcTransportConfig);

bind(ChannelzScheduledReporter.class).toInstance(reporter);
bind(ChannelzScheduledReporter.class).toInstance(this.reporter);

// dns executor
bind(ExecutorService.class).toProvider(DnsExecutorServiceProvider.class).in(Scopes.SINGLETON);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ public DataSender<SpanType> get() {
senderExecutorQueueSize, messageConverter,
reconnectExecutor, channelFactory, failState, grpcTransportConfig.getSpanRpcMaxAgeMillis());


registerChannelzReporter(spanGrpcDataSender);
if (grpcTransportConfig.isSpanEnableStatLogging()) {
registerChannelzReporter(spanGrpcDataSender);
}

return spanGrpcDataSender;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2023 NAVER Corp.
*
* 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.
*/
package com.navercorp.pinpoint.profiler.sender.grpc.metric;

import com.google.common.annotations.VisibleForTesting;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;

import java.time.Duration;
import java.util.Objects;

/**
* @author youngjin.kim2
*/
public class ChannelzScheduledReporterBuilder {

private Duration reportPeriod = Duration.ofSeconds(60);

public ChannelzScheduledReporterBuilder acceptConfig(ProfilerConfig config) {
String reportPeriodStr = Objects.requireNonNull(config, "config").getGrpcStatLoggingPeriod();
this.reportPeriod = Duration.parse(reportPeriodStr);
return this;
}

@VisibleForTesting
ChannelzScheduledReporterBuilder setReportPeriod(Duration reportPeriod) {
this.reportPeriod = reportPeriod;
return this;
}

public ChannelzScheduledReporter build() {
if (this.reportPeriod.toMillis() <= 0) {
return new EmptyChannelzScheduledReporter();
} else {
return new DefaultChannelzScheduledReporter(this.reportPeriod);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.navercorp.pinpoint.profiler.sender.grpc.metric;

import com.google.common.base.MoreObjects;
import java.util.Objects;
import com.navercorp.pinpoint.common.util.CollectionUtils;
import com.navercorp.pinpoint.grpc.channelz.ChannelzUtils;
import io.grpc.InternalChannelz;
Expand All @@ -11,11 +10,10 @@

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class DefaultChannelzReporter implements ChannelzReporter {
private static final long TIMEOUT = 3000;

private final Logger logger;

private final InternalChannelz channelz = InternalChannelz.instance();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.navercorp.pinpoint.profiler.sender.grpc.metric;

import com.navercorp.pinpoint.common.profiler.concurrent.PinpointThreadFactory;
import java.util.Objects;
import com.navercorp.pinpoint.grpc.ExecutorUtils;

import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ScheduledExecutorService;
Expand All @@ -12,12 +13,24 @@
import java.util.concurrent.TimeUnit;

public class DefaultChannelzScheduledReporter implements ChannelzScheduledReporter {
private final ScheduledExecutorService scheduledExecutorService = newScheduledExecutorService();

private static final long REPORT_INITIAL_DELAY_MS = 1000;

private final ConcurrentMap<Long, ChannelzReporter> reporterMap = new ConcurrentHashMap<>();
private final ScheduledExecutorService scheduledExecutorService = newScheduledExecutorService();

private final long reportPeriodMillis;

private ScheduledExecutorService newScheduledExecutorService() {
String threadName = PinpointThreadFactory.DEFAULT_THREAD_NAME_PREFIX + DefaultChannelzScheduledReporter.class.getSimpleName();
public DefaultChannelzScheduledReporter(Duration reportPeriod) {
Objects.requireNonNull(reportPeriod, "reportPeriod");
this.reportPeriodMillis = reportPeriod.toMillis();
if (this.reportPeriodMillis <= 0) {
throw new IllegalArgumentException("Illegal report period: " + reportPeriod);
}
}
private static ScheduledExecutorService newScheduledExecutorService() {
String threadName = PinpointThreadFactory.DEFAULT_THREAD_NAME_PREFIX +
DefaultChannelzScheduledReporter.class.getSimpleName();
ThreadFactory threadFactory = new PinpointThreadFactory(threadName, true);
return new ScheduledThreadPoolExecutor(1, threadFactory);
}
Expand All @@ -35,7 +48,7 @@ public void registerRootChannel(final long id, final ChannelzReporter reporter)
public void run() {
reporter.reportRootChannel(id);
}
}, 1000, 60 * 1000, TimeUnit.MILLISECONDS);
}, REPORT_INITIAL_DELAY_MS, this.reportPeriodMillis, TimeUnit.MILLISECONDS);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2023 NAVER Corp.
*
* 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 implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.pinpoint.profiler.sender.grpc.metric;

import org.junit.jupiter.api.Test;

import java.time.Duration;

import static org.assertj.core.api.Assertions.assertThat;

/**
* @author youngjin.kim2
*/
public class ChannelzScheduledReporterBuilderTest {

@Test
public void shouldReturnEmptyWhenDurationIsZero() {
ChannelzScheduledReporter empty = new ChannelzScheduledReporterBuilder()
.setReportPeriod(Duration.ZERO)
.build();
assertThat(empty).isInstanceOf(EmptyChannelzScheduledReporter.class);

Duration zeroDuration = Duration.ofMillis(0);
ChannelzScheduledReporter empty2 = new ChannelzScheduledReporterBuilder()
.setReportPeriod(zeroDuration)
.build();
assertThat(empty2).isInstanceOf(EmptyChannelzScheduledReporter.class);
}

@Test
public void shouldReturnDefaultWhenDurationAboveZero() {
ChannelzScheduledReporter defaultReporter = new ChannelzScheduledReporterBuilder()
.setReportPeriod(Duration.ofMillis(1))
.build();
assertThat(defaultReporter).isInstanceOf(DefaultChannelzScheduledReporter.class);
}

}

0 comments on commit 091d898

Please sign in to comment.