All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.kairosdb.metrics4j.collectors.impl.TimestampCounter Maven / Gradle / Ivy

package org.kairosdb.metrics4j.collectors.impl;

import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.ToString;
import org.kairosdb.metrics4j.MetricsContext;
import org.kairosdb.metrics4j.collectors.Collector;
import org.kairosdb.metrics4j.collectors.TimeCollector;
import org.kairosdb.metrics4j.collectors.helpers.Cloneable;
import org.kairosdb.metrics4j.reporting.LongValue;
import org.kairosdb.metrics4j.reporting.MetricReporter;
import org.kairosdb.metrics4j.util.Clock;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 This collector records a count of timestamps during a configurable amount of time.
 The initial use of this collector was to count events going in and out of an event
 system.  The idea is to count all events that occur in a bucket of time and report
 them using a timestamp within that bucket.

 The default configuration can handle the same timestamp (rounded to the minute)
 being reported for just short of 2 weeks (13 ish days) before potentially overwriting
 the same timestamp when reporting data.

 Basically a timestamp (rounded to the minute) can be counted and reported for about 2 weeks
 each time it reports it will use a slightly different timestamp so as to not overwrite
 previous counts
 */
@ToString
@EqualsAndHashCode
public class TimestampCounter extends Cloneable implements TimeCollector
{
	private volatile Map m_timeBuckets = new HashMap<>();
	private Object m_mapLock = new Object();

	private final Clock m_clock;

	@Setter
	protected long truncateMillis = 20_000L; //Increments the reported timestamp every 20 sec

	@Setter
	protected long modTime = 60_000L;  //Aggregates report time to 1 minute intervals, this should match your reporting interval (defaults to 1 min)

	public TimestampCounter()
	{
		this(new Clock());
	}

	public TimestampCounter(Clock clock)
	{
		m_clock = clock;
	}


	@Override
	public void put(Instant time)
	{
		Instant bucketTime = time.truncatedTo(ChronoUnit.MINUTES);

		synchronized (m_mapLock)
		{
			AtomicLong counter = m_timeBuckets.computeIfAbsent(bucketTime, (key) -> new AtomicLong());

			counter.incrementAndGet();
		}
	}

	@Override
	public Collector clone()
	{
		TimestampCounter clone = (TimestampCounter) super.clone();
		clone.m_timeBuckets = new HashMap<>();
		clone.m_mapLock = new Object();

		return clone;
	}

	@Override
	public void init(MetricsContext context)
	{
		//nothing to do
	}

	@Override
	public void reportMetric(MetricReporter metricReporter)
	{
		Map timeBuckets;
		synchronized (m_mapLock)
		{
			timeBuckets = m_timeBuckets;
			m_timeBuckets = new ConcurrentHashMap<>();
		}

		long nowMillis = m_clock.now();

		long additionalMillis = (nowMillis / truncateMillis) % modTime;

		for (Instant instant : timeBuckets.keySet())
		{
			AtomicLong counter = timeBuckets.get(instant);

			metricReporter.put("count", new LongValue(counter.get()), instant.plusMillis(additionalMillis));
		}

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy