class TracerFactory {

    @SuppressWarnings("unchecked")
    public synchronized Tracer create(ServiceHost host) {
        Logger logger = Logger.getLogger(getClass().getName());
        String impl = XenonConfiguration.string(TracerFactory.class, "provider", null);

        if (impl == null) {
            return NoopTracerFactory.create();
        }
        impl = impl.toLowerCase();

        Class<TracerFactoryInterface> factoryClass;
        try {
            if (impl.equals(IMPL_JAEGER)) {
                factoryClass = (Class<TracerFactoryInterface>) Class
                        .forName("com.vmware.xenon.common.opentracing.Jaeger");
            } else if (impl.equals(IMPL_ZIPKIN)) {
                factoryClass = (Class<TracerFactoryInterface>) Class
                        .forName("com.vmware.xenon.common.opentracing.Zipkin");
            } else {
                throw new RuntimeException(String.format("Bad tracer type %s", impl));
            }
        } catch (ClassNotFoundException e) {
            logger.log(Level.SEVERE, "Failed to load impl class", e);
            throw new RuntimeException(String.format("Could not load impl for %s", impl), e);
        }

        TracerFactoryInterface factory;
        try {
            factory = factoryClass.newInstance();
        } catch (ReflectiveOperationException e) {
            logger.log(Level.SEVERE, "Failed to instantiate tracer factory", e);
            throw new RuntimeException(String.format("Could not instantiate factory for %s", impl), e);
        }

        return factory.create(host);
    }

}