@Override
    public ObjectNode encode(Metric metric, CodecContext context) {
        checkNotNull(metric, "Metric cannot be null");

        ObjectNode objectNode = context.mapper().createObjectNode();
        ObjectNode dataNode = context.mapper().createObjectNode();

        if (metric instanceof Counter) {
            dataNode.put(COUNTER, ((Counter) metric).getCount());
            objectNode.set(COUNTER, dataNode);
        } else if (metric instanceof Gauge) {
            objectNode.put(VALUE, ((Gauge) metric).getValue().toString());
            objectNode.set(GAUGE, dataNode);
        } else if (metric instanceof Meter) {
            dataNode.put(COUNTER, ((Meter) metric).getCount());
            dataNode.put(MEAN_RATE, ((Meter) metric).getMeanRate());
            dataNode.put(ONE_MIN_RATE, ((Meter) metric).getOneMinuteRate());
            dataNode.put(FIVE_MIN_RATE, ((Meter) metric).getFiveMinuteRate());
            dataNode.put(FIFT_MIN_RATE, ((Meter) metric).getFifteenMinuteRate());
            objectNode.set(METER, dataNode);
        } else if (metric instanceof Histogram) {
            dataNode.put(COUNTER, ((Histogram) metric).getCount());
            dataNode.put(MEAN, ((Histogram) metric).getSnapshot().getMean());
            dataNode.put(MIN, ((Histogram) metric).getSnapshot().getMin());
            dataNode.put(MAX, ((Histogram) metric).getSnapshot().getMax());
            dataNode.put(STDDEV, ((Histogram) metric).getSnapshot().getStdDev());
            objectNode.set(HISTOGRAM, dataNode);
        } else if (metric instanceof Timer) {
            dataNode.put(COUNTER, ((Timer) metric).getCount());
            dataNode.put(MEAN_RATE, ((Timer) metric).getMeanRate());
            dataNode.put(ONE_MIN_RATE, ((Timer) metric).getOneMinuteRate());
            dataNode.put(FIVE_MIN_RATE, ((Timer) metric).getFiveMinuteRate());
            dataNode.put(FIFT_MIN_RATE, ((Timer) metric).getFifteenMinuteRate());
            dataNode.put(MEAN, nanoToMs(((Timer) metric).getSnapshot().getMean()));
            dataNode.put(MIN, nanoToMs(((Timer) metric).getSnapshot().getMin()));
            dataNode.put(MAX, nanoToMs(((Timer) metric).getSnapshot().getMax()));
            dataNode.put(STDDEV, nanoToMs(((Timer) metric).getSnapshot().getStdDev()));
            objectNode.set(TIMER, dataNode);
        }
        return objectNode;
    }
@Test
    public void testMetricEncode() {
        Counter counter = new Counter();
        Meter meter = new Meter();
        Timer timer = new Timer();

        counter.inc();
        meter.mark();
        timer.update(1, TimeUnit.MILLISECONDS);

        ObjectNode counterJson = metricCodec.encode(counter, context);
        assertThat(counterJson.get("counter"), matchesMetric(counter));

        ObjectNode meterJson = metricCodec.encode(meter, context);
        assertThat(meterJson.get("meter"), matchesMetric(meter));

        ObjectNode timerJson = metricCodec.encode(timer, context);
        assertThat(timerJson.get("timer"), matchesMetric(timer));
    }