<commit_before>package com.nhn.pinpoint.profiler.monitor;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.nhn.pinpoint.profiler.monitor.codahale.gc.GarbageCollector;
import com.nhn.pinpoint.profiler.monitor.codahale.gc.GarbageCollectorFactory;
import com.nhn.pinpoint.thrift.dto.TAgentStat;
import com.nhn.pinpoint.thrift.dto.TJvmGc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nhn.pinpoint.common.util.PinpointThreadFactory;
import com.nhn.pinpoint.profiler.sender.DataSender;

/**
 * AgentStat monitor
 * 
 * @author harebox
 * 
 */
public class AgentStatMonitor {

    private static final long DEFAULT_INTERVAL = 1000 * 5;

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1, new PinpointThreadFactory("Pinpoint-stat-monitor", true));

	private final DataSender dataSender;
	private final String agentId;

	public AgentStatMonitor(DataSender dataSender, String agentId) {
        if (dataSender == null) {
            throw new NullPointerException("dataSender must not be null");
        }
        if (agentId == null) {
            throw new NullPointerException("agentId must not be null");
        }
        this.dataSender = dataSender;
        this.agentId = agentId;
	}


	public void start() {
		CollectJob job = new CollectJob(dataSender);
		// FIXME 설정에서 수집 주기를 가져올 수 있어야 한다.
		long interval = DEFAULT_INTERVAL;
		long wait = 0;
		
		executor.scheduleAtFixedRate(job, wait, interval, TimeUnit.MILLISECONDS);
		logger.info("AgentStat monitor started");
	}

	public void stop() {
		executor.shutdown();
        try {
            executor.awaitTermination(3000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        logger.info("AgentStat monitor stopped");
	}

    private class CollectJob implements Runnable {

		private final DataSender dataSender;
		private final GarbageCollector garbageCollector;
        private final String agentId;

		public CollectJob(DataSender dataSender) {
            if (dataSender == null) {
                throw new NullPointerException("dataSender must not be null");
            }
            this.dataSender = dataSender;
            this.agentId = AgentStatMonitor.this.agentId;

			// GarbageCollectorFactory 타입을 확인한다.
			this.garbageCollector = GarbageCollectorFactory.createGarbageCollector();
			if (logger.isInfoEnabled()) {
				logger.info("found : {}", this.garbageCollector);
			}
		}



        public void run() {
			try {
                // TAgentStat 객체를 준비한다.
                // TODO TAgentStat을 재활용시 datasender가 별도의 thread이기 때문에. multithread문제가 생길수 있음.
                final TAgentStat agentStat = new TAgentStat();
                agentStat.setAgentId(agentId);
				agentStat.setTimestamp(System.currentTimeMillis());
                final TJvmGc gc = this.garbageCollector.collect();
                agentStat.setGc(gc);

                this.dataSender.send(agentStat);
			} catch (Exception ex) {
				logger.warn("AgentStat collect failed. Caused:{}", ex.getMessage(), ex);
			}
		}
	}

}<commit_msg>[강운덕] [Profiler-8] 5.TAgentStat를 재사용하는 부분으로 인해 잠재적 멀티 Thread이슈가 발생할수 있음.  - datasend로 객체를 던질경우 datasender는 다른 thread라 멀티쓰레드에서 map등을 사용할 경우 무한루프가 발생가능함.  - 재사용시 데이터 변경으로 인해 datasender thread의 속도가 느릴경우 잘못된 데이터를 던질수 있음.<commit_after>package com.nhn.pinpoint.profiler.monitor;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.nhn.pinpoint.profiler.monitor.codahale.gc.GarbageCollector;
import com.nhn.pinpoint.profiler.monitor.codahale.gc.GarbageCollectorFactory;
import com.nhn.pinpoint.thrift.dto.TAgentStat;
import com.nhn.pinpoint.thrift.dto.TJvmGc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nhn.pinpoint.common.util.PinpointThreadFactory;
import com.nhn.pinpoint.profiler.sender.DataSender;

/**
 * AgentStat monitor
 * 
 * @author harebox
 * 
 */
public class AgentStatMonitor {

    private static final long DEFAULT_INTERVAL = 1000 * 5;

	private final Logger logger = LoggerFactory.getLogger(this.getClass());

	private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1, new PinpointThreadFactory("Pinpoint-stat-monitor", true));

	private final DataSender dataSender;
	private final String agentId;
    private final GarbageCollector garbageCollector;

	public AgentStatMonitor(DataSender dataSender, String agentId) {
        if (dataSender == null) {
            throw new NullPointerException("dataSender must not be null");
        }
        if (agentId == null) {
            throw new NullPointerException("agentId must not be null");
        }
        this.dataSender = dataSender;
        this.agentId = agentId;
        this.garbageCollector = GarbageCollectorFactory.createGarbageCollector();
        if (logger.isInfoEnabled()) {
            logger.info("found : {}", this.garbageCollector);
        }
	}


	public void start() {
		CollectJob job = new CollectJob();
		// FIXME 설정에서 수집 주기를 가져올 수 있어야 한다.
		long interval = DEFAULT_INTERVAL;
		long wait = 0;
		
		executor.scheduleAtFixedRate(job, wait, interval, TimeUnit.MILLISECONDS);
		logger.info("AgentStat monitor started");
	}

	public void stop() {
		executor.shutdown();
        try {
            executor.awaitTermination(3000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        logger.info("AgentStat monitor stopped");
	}

    private class CollectJob implements Runnable {

        public void run() {
			try {
                // TAgentStat 객체를 준비한다.
                // TODO TAgentStat을 재활용시 datasender가 별도의 thread이기 때문에. multithread문제가 생길수 있음.
                final TAgentStat agentStat = new TAgentStat();
                agentStat.setAgentId(agentId);
				agentStat.setTimestamp(System.currentTimeMillis());
                final TJvmGc gc = garbageCollector.collect();
                agentStat.setGc(gc);

                dataSender.send(agentStat);
			} catch (Exception ex) {
				logger.warn("AgentStat collect failed. Caused:{}", ex.getMessage(), ex);
			}
		}
	}

}
{'fraction_non_alphanumeric': 0.09552845528455285, 'fraction_numerical': 0.004377736085053158, 'mean_word_length': 3.159297789336801, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7250814', 'n_tokens_mistral': 2159, 'n_tokens_neox': 2154, 'n_words': 432}