001/*
002 * (C) Copyright 2017 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 */
017package org.nuxeo.ecm.core.cache;
018
019import java.io.Serializable;
020
021import org.nuxeo.runtime.metrics.MetricsService;
022
023import com.codahale.metrics.Counter;
024import com.codahale.metrics.Gauge;
025import com.codahale.metrics.MetricRegistry;
026import com.codahale.metrics.RatioGauge;
027import com.codahale.metrics.SharedMetricRegistries;
028
029public class CacheMetrics extends CacheWrapper {
030
031    protected final MetricRegistry registry;
032
033    protected final Counter read;
034
035    protected final Counter read_hit;
036
037    protected final Counter read_miss;
038
039    protected final RatioGauge read_hit_ratio;
040
041    protected final Counter write;
042
043    protected final Counter invalidation;
044
045    protected final Gauge<Long> size;
046
047    protected final String READ_HIT_NAME = nameOf("read-hit-counter");
048
049    protected final String READ_HIT_RATIO_NAME = nameOf("read-hit-ratio");
050
051    protected final String READ_MISS_NAME = nameOf("read-miss-counter");
052
053    protected final String READ_NAME = nameOf("read-counter");
054
055    protected final String WRITE_NAME = nameOf("write-counter");
056
057    protected final String INVALIDATE_ALL_NAME = nameOf("invalidate-all-counter");
058
059    protected final String SIZE_NAME = nameOf("size");
060
061    public CacheMetrics(Cache cache) {
062        super(cache);
063        registry = SharedMetricRegistries.getOrCreate(MetricsService.class.getName());
064        read = registry.counter(READ_NAME);
065        read_hit = registry.counter(READ_HIT_NAME);
066        read_miss = registry.counter(READ_MISS_NAME);
067        registry.register(READ_HIT_RATIO_NAME, read_hit_ratio = new RatioGauge() {
068
069            @Override
070            protected Ratio getRatio() {
071                Ratio ratio = Ratio.of(read_hit.getCount(), read.getCount());
072                return ratio;
073            }
074        });
075        write = registry.counter(WRITE_NAME);
076        invalidation = registry.counter(INVALIDATE_ALL_NAME);
077        registry.register(SIZE_NAME, size = new Gauge<Long>() {
078
079            @Override
080            public Long getValue() {
081                return Long.valueOf(cache.getSize());
082            }
083
084        });
085    }
086
087    protected String nameOf(String name) {
088        return MetricRegistry.name("nuxeo", "cache", cache.getName(), name);
089    }
090
091    @Override
092    protected void onStop() {
093        registry.remove(READ_NAME);
094        registry.remove(READ_HIT_NAME);
095        registry.remove(READ_HIT_RATIO_NAME);
096        registry.remove(READ_MISS_NAME);
097        registry.remove(WRITE_NAME);
098        registry.remove(INVALIDATE_ALL_NAME);
099        registry.remove(SIZE_NAME);
100    }
101
102    @Override
103    public Serializable get(String key) {
104        Serializable value = cache.get(key);
105        read.inc();
106        if (value != null || cache.hasEntry(key)) {
107            read_hit.inc();
108        } else {
109            read_miss.inc();
110        }
111        return value;
112    }
113
114    @Override
115    public void put(String key, Serializable value) {
116        try {
117            super.put(key, value);
118        } finally {
119            write.inc();
120        }
121    }
122
123    @Override
124    public void invalidate(String key) {
125        cache.invalidate(key);
126    }
127
128    @Override
129    public void invalidateAll() {
130        try {
131            cache.invalidateAll();
132        } finally {
133            invalidation.inc();
134        }
135    }
136
137    @Override
138    public long getSize() {
139        return cache.getSize();
140    }
141
142}