protected void sendVMMetrics(long epoch) {
    newEvent()
        .time(epoch)
        .service(service("jvm", "memory", "heap-usage"))
        .metric(vm.heapUsage())
        .send();
    newEvent()
        .time(epoch)
        .service(service("jvm", "memory", "non-heap-usage"))
        .metric(vm.nonHeapUsage())
        .send();
    for (Entry<String, Double> pool : vm.memoryPoolUsage().entrySet()) {
      newEvent()
          .time(epoch)
          .service(service("jvm", "memory", "pool-usage", pool.getKey()))
          .metric(pool.getValue())
          .send();
    }
    newEvent()
        .time(epoch)
        .service(service("jvm", "thread", "daemon-count"))
        .metric(vm.daemonThreadCount())
        .send();
    newEvent()
        .time(epoch)
        .service(service("jvm", "thread", "count"))
        .metric(vm.threadCount())
        .send();
    newEvent().time(epoch).service(service("jvm", "uptime")).metric(vm.uptime()).send();
    newEvent()
        .time(epoch)
        .service(service("jvm", "fd-usage"))
        .metric(vm.fileDescriptorUsage())
        .send();

    for (Entry<Thread.State, Double> entry : vm.threadStatePercentages().entrySet()) {
      newEvent()
          .time(epoch)
          .service(service("jvm", "thread", "state", entry.getKey().toString().toLowerCase()))
          .metric(entry.getValue())
          .send();
    }

    for (Entry<String, VirtualMachineMetrics.GarbageCollectorStats> entry :
        vm.garbageCollectors().entrySet()) {
      newEvent()
          .time(epoch)
          .service(service("jvm", "gc", entry.getKey(), "time"))
          .metric(entry.getValue().getTime(TimeUnit.MILLISECONDS))
          .send();
      newEvent()
          .time(epoch)
          .service(service("jvm", "gc", entry.getKey(), "runs"))
          .metric(entry.getValue().getRuns())
          .send();
    }
  }
  public static final class ConfigBuilder {
    // Default values for Config
    private MetricsRegistry metricsRegistry = Metrics.defaultRegistry();
    private MetricPredicate predicate = MetricPredicate.ALL;
    private boolean printVMMetrics = true;
    private String host = "localhost";
    private int port = 5555;
    private long period = 60;
    private TimeUnit unit = TimeUnit.SECONDS;
    private String prefix = null;
    private String separator = " ";
    private final VirtualMachineMetrics vm = VirtualMachineMetrics.getInstance();
    private Clock clock = Clock.defaultClock();
    private String name = "riemann-reporter";
    private String localHost = null;

    private ConfigBuilder() {}

    public Config build() {
      return new Config(
          metricsRegistry,
          predicate,
          printVMMetrics,
          host,
          port,
          period,
          unit,
          prefix,
          separator,
          clock,
          name,
          localHost);
    }

    public ConfigBuilder metricsRegistry(MetricsRegistry r) {
      metricsRegistry = r;
      return this;
    }

    public ConfigBuilder predicate(MetricPredicate p) {
      predicate = p;
      return this;
    }

    public ConfigBuilder printVMMetrics(Boolean p) {
      printVMMetrics = p;
      return this;
    }

    public ConfigBuilder host(String h) {
      host = h;
      return this;
    }

    public ConfigBuilder port(int p) {
      port = p;
      return this;
    }

    public ConfigBuilder period(long p) {
      period = p;
      return this;
    }

    public ConfigBuilder unit(TimeUnit t) {
      unit = t;
      return this;
    }

    public ConfigBuilder prefix(String p) {
      prefix = p;
      return this;
    }

    public ConfigBuilder separator(String s) {
      separator = s;
      return this;
    }

    public ConfigBuilder clock(Clock c) {
      clock = c;
      return this;
    }

    public ConfigBuilder name(String n) {
      name = n;
      return this;
    }

    public ConfigBuilder localHost(String l) {
      localHost = l;
      return this;
    }
  }
  public static class Config {

    public final MetricsRegistry metricsRegistry;
    public final MetricPredicate predicate;
    public final boolean printVMMetrics;
    public final String host;
    public final int port;
    public final long period;
    public final TimeUnit unit;
    public final String prefix;
    public final String separator;
    public final VirtualMachineMetrics vm = VirtualMachineMetrics.getInstance();
    public final Clock clock;
    public final String name;
    public final String localHost;

    private Config(
        MetricsRegistry metricsRegistry,
        MetricPredicate predicate,
        boolean printVMMetrics,
        String host,
        int port,
        long period,
        TimeUnit unit,
        String prefix,
        String separator,
        Clock clock,
        String name,
        String localHost) {
      this.metricsRegistry = metricsRegistry;
      this.predicate = predicate;
      this.printVMMetrics = printVMMetrics;
      this.host = host;
      this.port = port;
      this.period = period;
      this.unit = unit;
      this.prefix = prefix;
      this.separator = separator;
      this.clock = clock;
      this.name = name;
      this.localHost = localHost;
    }

    public static ConfigBuilder newBuilder() {
      return new ConfigBuilder();
    }

    @Override
    public String toString() {
      return "Config{"
          + "print_metrics:"
          + printVMMetrics
          + ", host:"
          + host
          + ", port:"
          + port
          + ", period:"
          + period
          + ", unit:"
          + unit
          + ", prefix:"
          + prefix
          + ", separator:"
          + separator
          + ", clock:"
          + clock
          + ", name:"
          + name
          + ", localhost:"
          + localHost
          + ", metrics_registry:"
          + metricsRegistry
          + ", predicate:"
          + predicate
          + "}";
    }
  }
  public static class Config {
    public MetricsRegistry metricsRegistry = Metrics.defaultRegistry();
    public MetricPredicate predicate = MetricPredicate.ALL;
    public boolean printVMMetrics = false;
    public String host = "localhost";
    public int port = 5555;
    public long period = 60;
    public TimeUnit unit = TimeUnit.SECONDS;
    public String prefix = null;
    public String separator = " ";
    public final VirtualMachineMetrics vm = VirtualMachineMetrics.getInstance();
    public Clock clock = Clock.defaultClock();
    public String name = "riemann-reporter";
    public String localHost = null;

    public Config() {}

    public Config metricsRegistry(MetricsRegistry r) {
      metricsRegistry = r;
      return this;
    }

    public Config predicate(MetricPredicate p) {
      predicate = p;
      return this;
    }

    public Config printVMMetrics(Boolean p) {
      printVMMetrics = p;
      return this;
    }

    public Config host(String h) {
      host = h;
      return this;
    }

    public Config port(int p) {
      port = p;
      return this;
    }

    public Config period(long p) {
      period = p;
      return this;
    }

    public Config unit(TimeUnit t) {
      unit = t;
      return this;
    }

    public Config prefix(String p) {
      prefix = p;
      return this;
    }

    public Config separator(String s) {
      separator = s;
      return this;
    }

    public Config clock(Clock c) {
      clock = c;
      return this;
    }

    public Config name(String n) {
      name = n;
      return this;
    }

    public Config localHost(String l) {
      localHost = l;
      return this;
    }
  }