package com.torodb.core.metrics;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.inject.Singleton;
import javax.management.ObjectName;

import com.codahale.metrics.Counter;
import com.codahale.metrics.ExponentiallyDecayingReservoir;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.JmxReporter;
import com.codahale.metrics.Meter;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.ObjectNameFactory;
import com.codahale.metrics.Timer;

@Singleton
public class ToroMetricRegistry extends MetricRegistry  {
	
	private final MbeanNameFactory mbeanNameFactory = new MbeanNameFactory();
	
	public ToroMetricRegistry() {
		super();
		final JmxReporter reporter = JmxReporter
				.forRegistry(this)
				.inDomain("torodb")
				.createsObjectNamesWith(mbeanNameFactory)
				.build();
		reporter.start();
	}

	public Counter counter(MetricName name) {
		mbeanNameFactory.registerName(name);
		Counter counter = counter(name.getMetricName());
		return counter;
	}

	public Meter meter(MetricName name) {
		mbeanNameFactory.registerName(name);
		Meter meter = meter(name.getMetricName());
		return meter;
	}

	public Histogram histogram(MetricName name) {
		mbeanNameFactory.registerName(name);
		Histogram histogram = register(name, new Histogram(new ExponentiallyDecayingReservoir()));
		return histogram;
	}

	public Timer timer(MetricName name) {
		mbeanNameFactory.registerName(name);
		Timer timer = register(name, new Timer());
		return timer;
	}

	public <T extends Metric> T register(MetricName name, T metric) {
		try {
			register(name.getMetricName(), metric);
			return metric;
		} catch (IllegalArgumentException e) {
			Metric existing = this.getMetrics().get(name.getMetricName());
			return (T) existing;
		}
	}

	public boolean remove(MetricName name) {
		boolean removed = remove(name.getMetricName());
		return removed;
	}
	
	private static class MbeanNameFactory implements ObjectNameFactory{
		
		private Map<String,ObjectName> names = new ConcurrentHashMap<>();
		
		private void registerName(MetricName name){
			names.put(name.getMetricName(), name.getMBeanName());
		}
		
		@Override
		public ObjectName createName(String type, String domain, String name) {
			return names.computeIfAbsent(name, n -> {
				try {
					return new ObjectName(domain, type, name);
				} catch (Exception e) {
					return null;
				}
			});
		}
	}
	
}

@@ -27,16 +27,37 @@
 trics;%0A%0A
+import java.io.File;%0A
 import j
@@ -70,16 +70,16 @@
 il.Map;%0A
-
 import j
@@ -116,16 +116,54 @@
 HashMap;
+%0Aimport java.util.concurrent.TimeUnit;
 %0A%0Aimport
@@ -257,24 +257,65 @@
 cs.Counter;%0A
+import com.codahale.metrics.CsvReporter;%0A
 import com.c
@@ -900,32 +900,8 @@
 is)%0A
-%09%09%09%09.inDomain(%22torodb%22)%0A
 %09%09%09%09
@@ -1691,24 +1691,24 @@
 tric) %7B%0A
-
 %09%09try %7B%0A
 %09%09%09regis
@@ -1699,16 +1699,56 @@
 %09%09try %7B%0A
+%09%09%09mbeanNameFactory.registerName(name);%0A
 %09%09%09regis

Fix metric name registration for JMX when factory methods are not used