<commit_before>package com.custardsource.parfait.timing;

import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

import com.custardsource.parfait.MonitorableRegistry;
import com.custardsource.parfait.MonitoredCounter;

/**
 * A class to provide a {@link EventMetricCollector} to each {@link Timeable} on demand, guaranteed
 * to be thread-safe as long is it's only ever used by the requesting thread.
 */
public class EventTimer {

    /**
     * Setting this {@link Logger} to DEBUG level will list all the created metrics in a
     * tab-delimited format, useful for importing elsewhere
     */
    private static final Logger LOG = Logger.getLogger(EventTimer.class);

    private final Map<Timeable, EventCounters> perTimeableCounters = new ConcurrentHashMap<Timeable, EventCounters>();

    private final ThreadValue<EventMetricCollector> metricCollectors = new ThreadValue.WeakReferenceThreadMap<EventMetricCollector>() {
        @Override
        protected EventMetricCollector initialValue() {
            return new EventMetricCollector(perTimeableCounters);
        }
    };
    
    
    /**
     * Holds the singleton total counters which are used across all events. The key is the
     * metric name
     */
    private final Map<String, MonitoredCounter> totalCountersAcrossEvents = new HashMap<String, MonitoredCounter>();
    
    private final ThreadMetricSuite metricSuite;
    private final String prefix;
    private final MonitorableRegistry registry;

    public EventTimer(String prefix, MonitorableRegistry registry, ThreadMetricSuite metrics,
            boolean enableCpuCollection, boolean enableContentionCollection) {
        this.metricSuite = metrics;
        this.prefix = prefix;
        this.registry = registry;
        if (enableCpuCollection) {
            ManagementFactory.getThreadMXBean().setThreadCpuTimeEnabled(true);
        }
        if (enableContentionCollection) {
            ManagementFactory.getThreadMXBean().setThreadContentionMonitoringEnabled(true);
        }
    }

    public EventMetricCollector getCollector() {
        return metricCollectors.get();
    }

    public void registerTimeable(Timeable timeable, String beanName) {
        timeable.setEventTimer(this);
        perTimeableCounters.put(timeable, getCounterSet(beanName));
    }

    private EventCounters getCounterSet(String beanName) {
        EventMetricCounters invocationCounter = createEventMetricCounters(beanName, "count",
                "Total number of times the event was directly triggered");
        EventCounters counters = new EventCounters(invocationCounter);

        for (ThreadMetric metric : metricSuite.metrics()) {
            EventMetricCounters timingCounter = createEventMetricCounters(beanName, metric
                    .getCounterSuffix(), metric.getDescription());
            counters.addMetric(metric, timingCounter);
        }

        return counters;
    }

    private MonitoredCounter createMetric(String beanName, String metric, String description) {
        String metricName = getMetricName(beanName, metric);
        String metricDescription = String.format(description, beanName);
        LOG.debug("Created metric: " + metricName + "\t" + metricDescription);
        return new MonitoredCounter(metricName, metricDescription, registry);
    }

    private EventMetricCounters createEventMetricCounters(String beanName, String metric,
            String metricDescription) {
        MonitoredCounter metricCounter = createMetric(beanName, metric, metricDescription + " ["
                + beanName + "]");
        MonitoredCounter totalCounter;

        totalCounter = totalCountersAcrossEvents.get(metric);
        if (totalCounter == null) {
            totalCounter = new MonitoredCounter(getTotalMetricName(metric), metricDescription
                    + " [TOTAL]", registry);
            totalCountersAcrossEvents.put(metric, totalCounter);
        }

        return new EventMetricCounters(metricCounter, totalCounter);
    }

    private String getMetricName(String beanName, String metric) {
        // TODO do name cleanup elsewhere
        return prefix + "." + beanName.replace("/", "") + "." + metric;
    }

    private String getTotalMetricName(String metric) {
        return prefix + ".total." + metric;
    }

    Integer getNumberOfTotalEventCounters() {
        return totalCountersAcrossEvents.size();
    }

    EventCounters getCounterSetForEvent(Object event) {
        return perTimeableCounters.get(event);
    }

    ThreadMetricSuite getMetricSuite() {
        return metricSuite;
    }
    
    Map<Thread, EventMetricCollector> getCollectorThreadMap() {
        return metricCollectors.asMap();
    }
}<commit_msg>Used correct type for map access<commit_after>package com.custardsource.parfait.timing;

import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

import com.custardsource.parfait.MonitorableRegistry;
import com.custardsource.parfait.MonitoredCounter;

/**
 * A class to provide a {@link EventMetricCollector} to each {@link Timeable} on demand, guaranteed
 * to be thread-safe as long is it's only ever used by the requesting thread.
 */
public class EventTimer {

    /**
     * Setting this {@link Logger} to DEBUG level will list all the created metrics in a
     * tab-delimited format, useful for importing elsewhere
     */
    private static final Logger LOG = Logger.getLogger(EventTimer.class);

    private final Map<Timeable, EventCounters> perTimeableCounters = new ConcurrentHashMap<Timeable, EventCounters>();

    private final ThreadValue<EventMetricCollector> metricCollectors = new ThreadValue.WeakReferenceThreadMap<EventMetricCollector>() {
        @Override
        protected EventMetricCollector initialValue() {
            return new EventMetricCollector(perTimeableCounters);
        }
    };
    
    
    /**
     * Holds the singleton total counters which are used across all events. The key is the
     * metric name
     */
    private final Map<String, MonitoredCounter> totalCountersAcrossEvents = new HashMap<String, MonitoredCounter>();
    
    private final ThreadMetricSuite metricSuite;
    private final String prefix;
    private final MonitorableRegistry registry;

    public EventTimer(String prefix, MonitorableRegistry registry, ThreadMetricSuite metrics,
            boolean enableCpuCollection, boolean enableContentionCollection) {
        this.metricSuite = metrics;
        this.prefix = prefix;
        this.registry = registry;
        if (enableCpuCollection) {
            ManagementFactory.getThreadMXBean().setThreadCpuTimeEnabled(true);
        }
        if (enableContentionCollection) {
            ManagementFactory.getThreadMXBean().setThreadContentionMonitoringEnabled(true);
        }
    }

    public EventMetricCollector getCollector() {
        return metricCollectors.get();
    }

    public void registerTimeable(Timeable timeable, String beanName) {
        timeable.setEventTimer(this);
        perTimeableCounters.put(timeable, getCounterSet(beanName));
    }

    private EventCounters getCounterSet(String beanName) {
        EventMetricCounters invocationCounter = createEventMetricCounters(beanName, "count",
                "Total number of times the event was directly triggered");
        EventCounters counters = new EventCounters(invocationCounter);

        for (ThreadMetric metric : metricSuite.metrics()) {
            EventMetricCounters timingCounter = createEventMetricCounters(beanName, metric
                    .getCounterSuffix(), metric.getDescription());
            counters.addMetric(metric, timingCounter);
        }

        return counters;
    }

    private MonitoredCounter createMetric(String beanName, String metric, String description) {
        String metricName = getMetricName(beanName, metric);
        String metricDescription = String.format(description, beanName);
        LOG.debug("Created metric: " + metricName + "\t" + metricDescription);
        return new MonitoredCounter(metricName, metricDescription, registry);
    }

    private EventMetricCounters createEventMetricCounters(String beanName, String metric,
            String metricDescription) {
        MonitoredCounter metricCounter = createMetric(beanName, metric, metricDescription + " ["
                + beanName + "]");
        MonitoredCounter totalCounter;

        totalCounter = totalCountersAcrossEvents.get(metric);
        if (totalCounter == null) {
            totalCounter = new MonitoredCounter(getTotalMetricName(metric), metricDescription
                    + " [TOTAL]", registry);
            totalCountersAcrossEvents.put(metric, totalCounter);
        }

        return new EventMetricCounters(metricCounter, totalCounter);
    }

    private String getMetricName(String beanName, String metric) {
        // TODO do name cleanup elsewhere
        return prefix + "." + beanName.replace("/", "") + "." + metric;
    }

    private String getTotalMetricName(String metric) {
        return prefix + ".total." + metric;
    }

    Integer getNumberOfTotalEventCounters() {
        return totalCountersAcrossEvents.size();
    }

    EventCounters getCounterSetForEvent(Timeable event) {
        return perTimeableCounters.get(event);
    }

    ThreadMetricSuite getMetricSuite() {
        return metricSuite;
    }
    
    Map<Thread, EventMetricCollector> getCollectorThreadMap() {
        return metricCollectors.asMap();
    }
}
{'fraction_non_alphanumeric': 0.07991739803820341, 'fraction_numerical': 0.00020650490449148167, 'mean_word_length': 3.282051282051282, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, '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': '5713499', 'n_tokens_mistral': 2459, 'n_tokens_neox': 2377, 'n_words': 613}