/** * Copyright 2015-2016 The OpenZipkin Authors * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package zipkin.collector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import static zipkin.internal.Util.checkNotNull; public final class InMemoryCollectorMetrics implements CollectorMetrics { private final ConcurrentHashMap<String, AtomicInteger> metrics; private final String messages; private final String messagesDropped; private final String bytes; private final String spans; private final String spansDropped; public InMemoryCollectorMetrics() { this(new ConcurrentHashMap<>(), null); } InMemoryCollectorMetrics(ConcurrentHashMap<String, AtomicInteger> metrics, String transport) { this.metrics = metrics; this.messages = scope("messages", transport); this.messagesDropped = scope("messagesDropped", transport); this.bytes = scope("bytes", transport); this.spans = scope("spans", transport); this.spansDropped = scope("spansDropped", transport); } @Override public InMemoryCollectorMetrics forTransport(String transportType) { return new InMemoryCollectorMetrics(metrics, checkNotNull(transportType, "transportType")); } @Override public void incrementMessages() { increment(messages, 1); } public int messages() { return get(messages); } @Override public void incrementMessagesDropped() { increment(messagesDropped, 1); } public int messagesDropped() { return get(messagesDropped); } @Override public void incrementBytes(int quantity) { increment(bytes, quantity); } public int bytes() { return get(bytes); } @Override public void incrementSpans(int quantity) { increment(spans, quantity); } public int spans() { return get(spans); } @Override public void incrementSpansDropped(int quantity) { increment(spansDropped, quantity); } public int spansDropped() { return get(spansDropped); } public void clear() { metrics.clear(); } private int get(String key) { AtomicInteger atomic = metrics.get(key); return atomic == null ? 0 : atomic.get(); } private void increment(String key, int quantity) { if (quantity == 0) return; while (true) { AtomicInteger metric = metrics.get(key); if (metric == null) { metric = metrics.putIfAbsent(key, new AtomicInteger(quantity)); if (metric == null) return; // won race creating the entry } while (true) { int oldValue = metric.get(); int update = oldValue + quantity; if (metric.compareAndSet(oldValue, update)) return; // won race updating } } } static String scope(String key, String transport) { return key + (transport == null ? "" : "." + transport); } }