class PrometheusMetricFactory implements MetricFactory {

    @Override
    public Metric create() {
        boolean isEnable = Boolean.valueOf(getProperty(ENABLE_PROP, "true"));
        if (!isEnable) {
            return new NoOpMetric();
        }

        // metric registry, should have 1-to-1 relationship with ConcurrentHashMap namesToCollectors for collector lookup
        CollectorRegistry registry = new CollectorRegistry();
        ConcurrentHashMap<String, Collector> namesToCollectors = new ConcurrentHashMap<>();

        // register JVM metrics
        if (Boolean.valueOf(getProperty(JVM_ENABLE_PROP, "false"))) {
            // for version = 0.6.1
            // DefaultExports.register(registry);

            // for version <= 0.6.0
            new StandardExports().register(registry);
            new MemoryPoolsExports().register(registry);
            new MemoryAllocationExports().register(registry);
            new BufferPoolsExports().register(registry);
            new GarbageCollectorExports().register(registry);
            new ThreadExports().register(registry);
            new ClassLoadingExports().register(registry);
            new VersionInfoExports().register(registry);
        }

        // exporter
        PrometheusExporter exporter = null;
        if (Boolean.valueOf(getProperty(HTTP_SERVER_ENABLE_PROP, "true"))) {
            // HTTP server for pulling
            int pullingPort = Integer.valueOf(getProperty(HTTP_SERVER_PORT_PROP, "8181"));
            try {
                exporter = new PrometheusPullServer(pullingPort, registry);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        // prometheus metric class
        String namespace = getProperty(NAMESPACE_PROP, "athenz_server");
        boolean isLabelRequestDomainNameEnable = Boolean.valueOf(getProperty(LABEL_REQUEST_DOMAIN_NAME_ENABLE_PROP, "false"));
        boolean isLabelPrincipalDomainNameEnable = Boolean.valueOf(getProperty(LABEL_PRINCIPAL_DOMAIN_NAME_ENABLE_PROP, "false"));
        boolean isLabelHttpMethodNameEnable = Boolean.valueOf(getProperty(LABEL_HTTP_METHOD_NAME_ENABLE_PROP, "false"));
        boolean isLabelHttpStatusNameEnable = Boolean.valueOf(getProperty(LABEL_HTTP_STATUS_NAME_ENABLE_PROP, "false"));
        boolean isLabelApiNameEnable = Boolean.valueOf(getProperty(LABEL_API_NAME_ENABLE_PROP, "false"));
        return new PrometheusMetric(
                registry,
                namesToCollectors,
                exporter,
                namespace,
                isLabelRequestDomainNameEnable,
                isLabelPrincipalDomainNameEnable,
                isLabelHttpMethodNameEnable,
                isLabelHttpStatusNameEnable,
                isLabelApiNameEnable);

    }

}