/** * Copyright 2015-2017 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.List; import zipkin.storage.AsyncSpanConsumer; import zipkin.storage.Callback; import zipkin.Codec; import zipkin.Span; /** * Instrumented applications report spans over a transport such as Kafka. Zipkin collectors receive * these messages, {@link Codec#readSpans(byte[]) decoding them into spans}, {@link * CollectorSampler#isSampled(Span) apply sampling}, and {@link AsyncSpanConsumer#accept(List, * Callback) queue them for storage}. * * <p>Callbacks on this type are invoked by zipkin collectors to improve the visibility of the * system. A typical implementation will report metrics to a telemetry system for analysis and * reporting. * * <h3>Spans Collected vs Queryable Spans</h3> * * <p>A span in the context of collection is <= span in the context of query. While it is advised * that instrumentation report complete spans, Instrumentation often patch the same span twice, ex * adding annotations. Also, RPC spans include at least 2 messages due to the client and the server * reporting separately. Finally, some storage components merge patches at ingest. For these * reasons, you should be cautious to alert on queryable spans vs stored spans, unless you control * the instrumentation in such a way that queryable spans/message is reliable. * * <h3>Key Relationships</h3> * * <p>The following relationships can be used to consider health of the tracing system. * <pre> * <ul> * <li>Successful Messages = {@link #incrementMessages() Accepted messages} - * {@link #incrementMessagesDropped() Dropped messages}. Alert when this is less than amount of * messages sent from instrumentation.</li> * <li>Stored spans <= {@link #incrementSpans(int) Accepted spans} - {@link * #incrementSpansDropped(int) Dropped spans}. Alert when this drops below the * {@link CollectorSampler#isSampled(Span) collection-tier sample rate}. * </li> * </ul> * </pre> */ public interface CollectorMetrics { /** * Those who wish to partition metrics by transport can call this method to include the transport * type in the backend metric key. * * <p>For example, an implementation may by default report {@link #incrementSpans(int) incremented * spans} to the key "zipkin.collector.span.accepted". When {@code metrics.forTransport("kafka"} * is called, the counter would report to "zipkin.collector.kafka.span.accepted" * * @param transportType ex "http", "scribe", "kafka" */ CollectorMetrics forTransport(String transportType); /** * Increments count of messages received, which contain 0 or more spans. Ex POST requests or Kafka * messages consumed. */ void incrementMessages(); /** * Increments count of messages that could not be read. Ex malformed content, or peer disconnect. */ void incrementMessagesDropped(); /** * Increments the count of spans read from a successful message. When bundling is used, accepted * spans will be a larger number than successful messages. */ void incrementSpans(int quantity); /** * Increments the number of bytes containing serialized spans in a message. * * <p>Note: this count should relate to the raw data structures, like json or thrift, and discount * compression, enveloping, etc. */ void incrementBytes(int quantity); /** * Increments the count of spans dropped for any reason. For example, failure queueing to storage * or sampling decisions. */ void incrementSpansDropped(int quantity); CollectorMetrics NOOP_METRICS = new CollectorMetrics() { @Override public CollectorMetrics forTransport(String transportType) { return this; } @Override public void incrementMessages() { } @Override public void incrementMessagesDropped() { } @Override public void incrementSpans(int quantity) { } @Override public void incrementBytes(int quantity) { } @Override public void incrementSpansDropped(int quantity) { } @Override public String toString() { return "NoOpCollectorMetrics"; } }; }