<commit_before>/**
 * 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.soundcloud.prometheus.hystrix;

import io.prometheus.client.Collector;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.Counter;
import io.prometheus.client.Histogram;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

/**
 * Implementation of a Prometheus Collector for Hystrix metrics.
 */
public class HystrixMetricsCollector extends Collector {

    private static final Logger LOG = LoggerFactory.getLogger(HystrixMetricsCollector.class);

    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Map<Gauge, List<Value>> gauges = new HashMap<>();
    private final Map<String, Histogram> histograms = new HashMap<>();
    private final Map<String, Counter> counters = new HashMap<>();

    private final String namespace;

    private CollectorRegistry registry = new CollectorRegistry();

    public HystrixMetricsCollector(String namespace) {
        this.namespace = namespace;
    }

    public void addGauge(String subsystem, String metric, String helpDoc,
                         Map<String, String> labels, Callable<Number> value) {

        lock.writeLock().lock();
        try {
            Gauge gauge = new Gauge(name(subsystem, metric), helpDoc);
            List<Value> values = gauges.get(gauge);
            if (values == null) {
                values = new ArrayList<>();
                gauges.put(gauge, values);
            }
            values.add(new Value(labels, value));
        } finally {
            lock.writeLock().unlock();
        }
    }

    public Histogram.Child addHistogram(String subsystem, String metric, String helpDoc,
                                        Map<String, String> labels) {
        lock.writeLock().lock();
        try {
            String name = name(subsystem, metric);
            Histogram histogram = histograms.get(name);
            if(histogram == null) {
                histogram = Histogram.build().name(name).help(helpDoc).
                        labelNames(labels.keySet().toArray(new String[]{})).create();
                histogram.register(registry);
                histograms.put(name, histogram);
            }
            Histogram.Child child = histogram.labels(labels.values().toArray(new String[]{}));
            return child;
        } finally {
            lock.writeLock().unlock();
        }
    }

    public Counter.Child addCounter(String subsystem, String metric, String helpDoc, Map<String, String> labels) {
        lock.writeLock().lock();
        try {
            String name = name(subsystem, metric);
            Counter counter = counters.get(name);
            if(counter == null) {
                counter = Counter.build().name(name(subsystem, metric)).help(helpDoc).
                        labelNames(labels.keySet().toArray(new String[]{})).create();
                counter.register(registry);
                counters.put(name, counter);
            }
            Counter.Child child = counter.labels(labels.values().toArray(new String[]{}));
            return child;
        } finally {
            lock.writeLock().unlock();
        }
    }

    private String name(String subsystem, String metric) {
        return (namespace != null)
                ? namespace + "_" + subsystem + "_" + metric
                : subsystem + "_" + metric;<commit_msg>use finer grained histogram for better statistics #4<commit_after>/**
 * 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
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * 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.soundcloud.prometheus.hystrix;

import io.prometheus.client.Collector;
import io.prometheus.client.CollectorRegistry;
import io.prometheus.client.Counter;
import io.prometheus.client.Histogram;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;

/**
 * Implementation of a Prometheus Collector for Hystrix metrics.
 */
public class HystrixMetricsCollector extends Collector {

    private static final Logger LOG = LoggerFactory.getLogger(HystrixMetricsCollector.class);

    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Map<Gauge, List<Value>> gauges = new HashMap<>();
    private final Map<String, Histogram> histograms = new HashMap<>();
    private final Map<String, Counter> counters = new HashMap<>();

    private final String namespace;

    private CollectorRegistry registry = new CollectorRegistry();

    public HystrixMetricsCollector(String namespace) {
        this.namespace = namespace;
    }

    public void addGauge(String subsystem, String metric, String helpDoc,
                         Map<String, String> labels, Callable<Number> value) {

        lock.writeLock().lock();
        try {
            Gauge gauge = new Gauge(name(subsystem, metric), helpDoc);
            List<Value> values = gauges.computeIfAbsent(gauge, k -> new ArrayList<>());
            values.add(new Value(labels, value));
        } finally {
            lock.writeLock().unlock();
        }
    }

    public Histogram.Child addHistogram(String subsystem, String metric, String helpDoc,
                                        Map<String, String> labels) {
        lock.writeLock().lock();
        try {
            String name = name(subsystem, metric);
            Histogram histogram = histograms.get(name);
            if(histogram == null) {
                histogram = Histogram.build().name(name).help(helpDoc)
                        .labelNames(labels.keySet().toArray(new String[]{}))
                        .exponentialBuckets(0.001, 1.31, 30)
                        .create();
                histogram.register(registry);
                histograms.put(name, histogram);
            }
            return histogram.labels(labels.values().toArray(new String[]{}));
        } finally {
            lock.writeLock().unlock();
        }
    }

    public Counter.Child addCounter(String subsystem, String metric, String helpDoc, Map<String, String> labels) {
        lock.writeLock().lock();
        try {
            String name = name(subsystem, metric);
            Counter counter = counters.get(name);
            if(counter == null) {
                counter = Counter.build().name(name(subsystem, metric)).help(helpDoc).
                        labelNames(labels.keySet().toArray(new String[]{})).create();
                counter.register(registry);
                counters.put(name, counter);
            }
            return counter.labels(labels.values().toArray(new String[]{}));
        } finally {
            lock.writeLock().unlock();
        }
    }

    private String name(String subsystem, String metric) {
        return (namespace != null)
                ? namespace + "_" + subsystem + "_" + metric
                : subsystem + "_" + metric;
{'fraction_non_alphanumeric': 0.10831910222005367, 'fraction_numerical': 0.002683581361307636, 'mean_word_length': 2.514359194170596, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6274892', 'n_tokens_mistral': 2161, 'n_tokens_neox': 2041, 'n_words': 581}