/*
* Copyright 2014 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.monitor;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.navercorp.pinpoint.common.util.PinpointThreadFactory;
import com.navercorp.pinpoint.profiler.context.module.AgentId;
import com.navercorp.pinpoint.profiler.context.module.AgentStartTime;
import com.navercorp.pinpoint.profiler.context.module.StatDataSender;
import com.navercorp.pinpoint.profiler.monitor.collector.AgentStatMetricCollector;
import com.navercorp.pinpoint.profiler.sender.DataSender;
import com.navercorp.pinpoint.profiler.sender.EmptyDataSender;
import com.navercorp.pinpoint.thrift.dto.TAgentStat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* AgentStat monitor
*
* @author harebox
* @author hyungil.jeong
*/
public class DefaultAgentStatMonitor implements AgentStatMonitor {
private static final long DEFAULT_COLLECTION_INTERVAL_MS = 1000 * 5;
private static final int DEFAULT_NUM_COLLECTIONS_PER_SEND = 6;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final long collectionIntervalMs;
private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1, new PinpointThreadFactory("Pinpoint-stat-monitor", true));
private final CollectJob collectJob;
@Inject
public DefaultAgentStatMonitor(@StatDataSender DataSender dataSender,
@AgentId String agentId, @AgentStartTime long agentStartTimestamp,
@Named("AgentStatCollector") AgentStatMetricCollector<TAgentStat> agentStatCollector) {
this(dataSender, agentId, agentStartTimestamp, agentStatCollector, DEFAULT_COLLECTION_INTERVAL_MS, DEFAULT_NUM_COLLECTIONS_PER_SEND);
}
public DefaultAgentStatMonitor(DataSender dataSender,
String agentId, long agentStartTimestamp,
AgentStatMetricCollector<TAgentStat> agentStatCollector,
long collectionInterval, int numCollectionsPerBatch) {
if (dataSender == null) {
throw new NullPointerException("dataSender must not be null");
}
if (agentId == null) {
throw new NullPointerException("agentId must not be null");
}
if (agentStatCollector == null) {
throw new NullPointerException("agentStatCollector must not be null");
}
this.collectionIntervalMs = collectionInterval;
this.collectJob = new CollectJob(dataSender, agentId, agentStartTimestamp, agentStatCollector, numCollectionsPerBatch);
preLoadClass(agentId, agentStartTimestamp, agentStatCollector);
}
// https://github.com/naver/pinpoint/issues/2881
// #2881 AppClassLoader and PinpointUrlClassLoader Circular dependency deadlock
// prevent deadlock for JDK6
// Single thread execution is more safe than multi thread execution.
// eg) executor.scheduleAtFixedRate(collectJob, 0(initialDelay is zero), this.collectionIntervalMs, TimeUnit.MILLISECONDS);
private void preLoadClass(String agentId, long agentStartTimestamp, AgentStatMetricCollector<TAgentStat> agentStatCollector) {
logger.debug("pre-load class start");
CollectJob collectJob = new CollectJob(EmptyDataSender.INSTANCE, agentId, agentStartTimestamp, agentStatCollector, 1);
collectJob.run();
logger.debug("pre-load class end");
}
@Override
public void start() {
executor.scheduleAtFixedRate(collectJob, this.collectionIntervalMs, this.collectionIntervalMs, TimeUnit.MILLISECONDS);
logger.info("AgentStat monitor started");
}
@Override
public void stop() {
executor.shutdown();
try {
executor.awaitTermination(3000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
logger.info("AgentStat monitor stopped");
}
}