Line data Source code
1 : // Copyright (C) 2015 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.metrics.dropwizard; 16 : 17 : import com.codahale.metrics.Gauge; 18 : import com.codahale.metrics.Metric; 19 : import com.codahale.metrics.MetricRegistry; 20 : import com.google.common.collect.ImmutableList; 21 : import com.google.common.collect.Maps; 22 : import com.google.gerrit.metrics.Description; 23 : import com.google.gerrit.metrics.Field; 24 : import java.util.Iterator; 25 : import java.util.Map; 26 : import java.util.concurrent.ConcurrentHashMap; 27 : 28 : /** Abstract callback metric broken down into buckets. */ 29 : abstract class BucketedCallback<V> implements BucketedMetric { 30 : private final DropWizardMetricMaker metrics; 31 : private final MetricRegistry registry; 32 : private final String name; 33 : private final Description.FieldOrdering ordering; 34 : protected final Field<?>[] fields; 35 : private final V zero; 36 : private final Map<Object, ValueGauge> cells; 37 : protected volatile Runnable trigger; 38 16 : private final Object lock = new Object(); 39 : 40 : BucketedCallback( 41 : DropWizardMetricMaker metrics, 42 : MetricRegistry registry, 43 : String name, 44 : Class<V> valueType, 45 : Description desc, 46 16 : Field<?>... fields) { 47 16 : this.metrics = metrics; 48 16 : this.registry = registry; 49 16 : this.name = name; 50 16 : this.ordering = desc.getFieldOrdering(); 51 16 : this.fields = fields; 52 16 : this.zero = CallbackMetricImpl0.zeroFor(valueType); 53 16 : this.cells = new ConcurrentHashMap<>(); 54 16 : } 55 : 56 : void doRemove() { 57 0 : for (Object key : cells.keySet()) { 58 0 : registry.remove(submetric(key)); 59 0 : } 60 0 : metrics.remove(name); 61 0 : } 62 : 63 : void doBeginSet() { 64 16 : for (ValueGauge g : cells.values()) { 65 0 : g.set = false; 66 0 : } 67 16 : } 68 : 69 : void doPrune() { 70 15 : Iterator<Map.Entry<Object, ValueGauge>> it = cells.entrySet().iterator(); 71 15 : while (it.hasNext()) { 72 15 : Map.Entry<Object, ValueGauge> e = it.next(); 73 15 : if (!e.getValue().set) { 74 0 : it.remove(); 75 0 : registry.remove(submetric(e.getKey())); 76 : } 77 15 : } 78 15 : } 79 : 80 : void doEndSet() { 81 16 : for (ValueGauge g : cells.values()) { 82 16 : if (!g.set) { 83 16 : g.value = zero; 84 : } 85 16 : } 86 16 : } 87 : 88 : ValueGauge getOrCreate(Object f1, Object f2) { 89 0 : return getOrCreate(ImmutableList.of(f1, f2)); 90 : } 91 : 92 : ValueGauge getOrCreate(Object f1, Object f2, Object f3) { 93 0 : return getOrCreate(ImmutableList.of(f1, f2, f3)); 94 : } 95 : 96 : ValueGauge getOrCreate(Object key) { 97 16 : ValueGauge c = cells.get(key); 98 16 : if (c != null) { 99 0 : return c; 100 : } 101 : 102 16 : synchronized (lock) { 103 16 : c = cells.get(key); 104 16 : if (c == null) { 105 16 : c = new ValueGauge(); 106 16 : registry.register(submetric(key), c); 107 16 : cells.put(key, c); 108 : } 109 16 : return c; 110 : } 111 : } 112 : 113 : private String submetric(Object key) { 114 16 : return DropWizardMetricMaker.name(ordering, name, name(key)); 115 : } 116 : 117 : abstract String name(Object key); 118 : 119 : @Override 120 : public Metric getTotal() { 121 0 : return null; 122 : } 123 : 124 : @Override 125 : public Field<?>[] getFields() { 126 0 : return fields; 127 : } 128 : 129 : @Override 130 : public Map<Object, Metric> getCells() { 131 0 : return Maps.transformValues(cells, in -> in); 132 : } 133 : 134 16 : final class ValueGauge implements Gauge<V> { 135 16 : volatile V value = zero; 136 : boolean set; 137 : 138 : @Override 139 : public V getValue() { 140 0 : Runnable t = trigger; 141 0 : if (t != null) { 142 0 : t.run(); 143 : } 144 0 : return value; 145 : } 146 : } 147 : }