All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.uber.jaeger.metrics.Metrics Maven / Gradle / Ivy

There is a newer version: 0.27.0
Show newest version
/*
 * Copyright (c) 2016, Uber Technologies, Inc
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.uber.jaeger.metrics;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

public class Metrics {
    public Metrics(StatsFactory factory) {
        for (Field field : Metrics.class.getDeclaredFields()) {
            if (!Counter.class.isAssignableFrom(field.getType()) &&
                !Timer.class.isAssignableFrom(field.getType())   &&
                !Gauge.class.isAssignableFrom(field.getType())) {
                // Some frameworks dynamically add code that this reflection will pick up
                // I only want this classes Stats based fields to be picked up.
                continue;
            }

            String metricName = "jaeger.";
            HashMap tags = new HashMap<>();

            Annotation[] annotations = field.getAnnotations();
            for (Annotation anno : annotations) {
                if (anno.annotationType().equals(Metric.class)) {
                    Metric metricAnno = (Metric) anno;
                    metricName += metricAnno.name();

                    Tag[] entries = metricAnno.tags();
                    for (Tag t : entries) {
                        tags.put(t.key(), t.value());
                    }
                }
            }

            try {
                if (field.getType().equals(Counter.class)) {
                    field.set(this, factory.createCounter(metricName, tags));
                } else if (field.getType().equals(Gauge.class)) {
                    field.set(this, factory.createGauge(metricName, tags));
                } else if (field.getType().equals(Timer.class)) {
                    field.set(this, factory.createTimer(metricName, tags));
                } else {
                    throw new RuntimeException("A field type that was neither Counter, Gauge, or Timer was parsed in reflection.");
                }
            } catch (ReflectiveOperationException e) {
                // This exception should only happen at the start of a program if the code below is not set up correctly.
                // As long as tests are run this code should never be thrown in production.
                throw new RuntimeException("No reflection exceptions should be thrown unless there is a fundamental error in your code set up.", e);
            }
        }
    }

    public static String addTagsToMetricName(String name, Map tags) {
        if (tags == null || tags.size() == 0) {
            return name;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(name);

        SortedSet sortedKeys = new TreeSet<>(tags.keySet());
        for (String key : sortedKeys) {
            sb.append(".");
            sb.append(key);
            sb.append("=");
            sb.append(tags.get(key));
        }
        return sb.toString();
    }

    public static Metrics fromStatsReporter(StatsReporter reporter) {
        return new Metrics(new StatsFactoryImpl(reporter));
    }

    @Metric(name = "traces", tags = {
            @Tag(key = "state", value = "started"),
            @Tag(key = "sampled", value = "y")
    })
    // Number of traces started by this tracer as sampled
    public Counter traceStartedSampled;

    @Metric(name = "traces", tags = {
            @Tag(key = "state", value = "started"),
            @Tag(key = "sampled", value = "n")
    })
    // Number of traces started by this tracer as not sampled
    public Counter traceStartedNotSampled;

    @Metric(name = "traces", tags = {
            @Tag(key = "state", value = "joined"),
            @Tag(key = "sampled", value = "y")
    })
    // Number of externally started sampled traces this tracer joined
    public Counter tracesJoinedSampled;


    @Metric(name = "traces", tags = {
            @Tag(key = "state", value = "joined"),
            @Tag(key = "sampled", value = "n")
    })
    // Number of externally started not-sampled traces this tracer joined
    public Counter tracesJoinedNotSampled;

    @Metric(name = "spans", tags = {
            @Tag(key = "state", value = "started"),
            @Tag(key = "group", value = "lifecycle")
    })
    // Number of sampled spans started by this tracer
    public Counter spansStarted;

    @Metric(name = "spans", tags = {
            @Tag(key = "state", value = "finished"),
            @Tag(key = "group", value = "lifecycle")
    })
    // Number of sampled spans started by this tracer
    public Counter spansFinished;

    @Metric(name = "spans", tags = {
            @Tag(key = "group", value = "sampling"),
            @Tag(key = "sampled", value = "y")
    })
    // Number of sampled spans started by this tracer
    public Counter spansSampled;

    @Metric(name = "spans", tags = {
            @Tag(key = "group", value = "sampling"),
            @Tag(key = "sampled", value = "n")
    })
    // Number of not-sampled spans started by this tracer
    public Counter spansNotSampled;

    @Metric(name = "decoding-errors")
    // Number of errors decoding tracing context
    public Counter decodingErrors;

    @Metric(name = "reporter-spans", tags = {
            @Tag(key = "state", value = "success")
    })
    // Number of spans successfully reported
    public Counter reporterSuccess;

    @Metric(name = "reporter-spans", tags = {
            @Tag(key = "state", value = "failure")
    })
    // Number of spans in failed attempts to report
    public Counter reporterFailure;

    @Metric(name = "spans", tags = {
            @Tag(key = "state", value = "dropped")
    })
    // Number of spans dropped due to internal queue overflow
    public Counter reporterDropped;

    @Metric(name = "reporter-queue")
    // Current number of spans in the reporter queue
    public Gauge reporterQueueLength;

    @Metric(name = "sampler", tags = {
            @Tag(key = "state", value = "retrieved")
    })
    // Number of times the Sampler succeeded to retrieve samping strategy
    public Counter samplerRetrieved;

    @Metric(name = "sampler", tags = {
            @Tag(key = "state", value = "updated"),
    })
    // Number of times the Sampler succeeded to retrieve and updateGauge sampling strategy
    public Counter samplerUpdated;

    @Metric(name = "sampler", tags = {
            @Tag(key = "state", value = "failure"),
            @Tag(key = "phase", value = "query")
    })
    // Number of times the Sampler failed to retrieve the sampling strategy
    public Counter samplerQueryFailure;

    @Metric(name = "sampler", tags = {
            @Tag(key = "state", value = "failure"),
            @Tag(key = "phase", value = "parsing")
    })
    // Number of times the Sampler failed to parse retrieved sampling strategy
    public Counter samplerParsingFailure;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy