附录D Metrics简介

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/77450039 注:本文是为了配合《Spark内核设计的艺术——架构设计与实现》一书的内容而编写,目的是为了节省成本、方便读者查阅。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beliefer/article/details/77450039

注:本文是为了配合《Spark内核设计的艺术——架构设计与实现》一书的内容而编写,目的是为了节省成本、方便读者查阅。书中附录D的内容都在本文呈现。

Metrics是codahale提供的第三方度量仓库。Metrics作为一款监控指标的度量类库,可以为第三方库提供辅助统计信息,还可以将度量数据发送给Ganglia和Graphite以提供图形化的监控。

      Metrics也采用了监听器模式,提供了Gauge、Counter、Meter、Histogram、Timer等度量工具类以及健康检查(HealthCheck)功能。想了解更多Metrics的内容,读者可以访问Metrics官网:http://metrics.dropwizard.io/3.2.2/

本文将对Metrics中的核心类进行介绍,方便读者对Spark度量系统更加细致深入的理解。

MetricRegistry

MetricRegistry是Metrics提供的度量容器,这里先列出MetricRegistry的主要结构。

public class MetricRegistry implements MetricSet {
  private final ConcurrentMap<String, Metric> metrics;
  private final List<MetricRegistryListener> listeners;
}
从上面代码可以看出MetricRegistry中会缓存各种度量和监听器,下面对MetricRegistry中的一些方法进行介绍。

1、name

功能描述:构建形如“字符串1.字符串2…字符串N-1.字符串N”这样的字符串。任何空值或空字符串都将被过滤。
    public static String name(String name, String... names) {
        final StringBuilder builder = new StringBuilder();
        append(builder, name);
        if (names != null) {
            for (String s : names) {
                append(builder, s);
            }
        }
        return builder.toString();
    }

2、notifyListenerOfAddedMetric

功能描述:当有新的Metric添加到ConcurrentMap<String, Metric> metrics时,调用此方法。根据Metric的子接口的不同,调用不同方法。例如:Gauge则调用监听器的onGaugeAdded;Counter则调用监听器的onCounterAdded;Histogram则调用监听器的onHistogramAdded。
    private void notifyListenerOfAddedMetric(MetricRegistryListener listener, Metric metric, String name) {
        if (metric instanceof Gauge) {
            listener.onGaugeAdded(name, (Gauge<?>) metric);
        } else if (metric instanceof Counter) {
            listener.onCounterAdded(name, (Counter) metric);
        } else if (metric instanceof Histogram) {
            listener.onHistogramAdded(name, (Histogram) metric);
        } else if (metric instanceof Meter) {
            listener.onMeterAdded(name, (Meter) metric);
        } else if (metric instanceof Timer) {
            listener.onTimerAdded(name, (Timer) metric);
        } else {
            throw new IllegalArgumentException("Unknown metric type: " + metric.getClass());
        }
    }

3、onMetricAdded

功能描述:当有新的Metric添加到ConcurrentMap<String, Metric> metrics时,调用此方法。遍历调用监听器缓存List<MetricRegistryListener> listeners中的所有监听器,调用notifyListenerOfAddedMetric。
    private void onMetricAdded(String name, Metric metric) {
        for (MetricRegistryListener listener : listeners) {
            notifyListenerOfAddedMetric(listener, metric, name);
        }
    }

4、register

功能描述:如果metric的类型是Metric并且metrics中还没有此metric,则将它添加到metrics;

如果Metric的类型是MetricSet,则MetricSet中包含的所有新的Metric添加到缓存ConcurrentMap<String, Metric> metrics;以上添加过程都伴随onMetricAdded的调用。
	public <T extends Metric> T register(String name, T metric) throws IllegalArgumentException {
        if (metric instanceof MetricSet) {
            registerAll(name, (MetricSet) metric);
        } else {
            final Metric existing = metrics.putIfAbsent(name, metric);
            if (existing == null) {
                onMetricAdded(name, metric);
            } else {
                throw new IllegalArgumentException("A metric named " + name + " already exists");
            }
        }
        return metric;
	}
	private void registerAll(String prefix, MetricSet metrics) throws IllegalArgumentException {
        for (Map.Entry<String, Metric> entry : metrics.getMetrics().entrySet()) {
            if (entry.getValue() instanceof MetricSet) {
                registerAll(name(prefix, entry.getKey()), (MetricSet) entry.getValue());
            } else {
                register(name(prefix, entry.getKey()), entry.getValue());
            }
        }
}

Gauge

Gauge是Metrics提供的用于估计度量值的特质,其实现如下:
public interface Gauge<T> extends Metric {
    /**
     * Returns the metric's current value.
     *
     * @return the metric's current value
     */
    T getValue();
}

Slf4jReporter

         Slf4jReporter Metrics提供的使用实现了Slf4j接口的实现类的方法,将度量输出到日志的类。

1、report

         功能描述:将度量输出到日志的方法。
    @Override
    public void report(SortedMap<String, Gauge> gauges,
                       SortedMap<String, Counter> counters,
                       SortedMap<String, Histogram> histograms,
                       SortedMap<String, Meter> meters,
                       SortedMap<String, Timer> timers) {
        if (loggerProxy.isEnabled(marker)) {
            for (Entry<String, Gauge> entry : gauges.entrySet()) {
                logGauge(entry.getKey(), entry.getValue());
            }

            for (Entry<String, Counter> entry : counters.entrySet()) {
                logCounter(entry.getKey(), entry.getValue());
            }

            for (Entry<String, Histogram> entry : histograms.entrySet()) {
                logHistogram(entry.getKey(), entry.getValue());
            }

            for (Entry<String, Meter> entry : meters.entrySet()) {
                logMeter(entry.getKey(), entry.getValue());
            }

            for (Entry<String, Timer> entry : timers.entrySet()) {
                logTimer(entry.getKey(), entry.getValue());
            }
        }
    }

2、logGauge

         功能描述:将估计度量输出到日志的方法。(备注: Slf4jReporter的 report 方法中分别对 Gauge Counter Histogram Meter Timer 进行输出,为说明问题,附录 D 只挑选了对 Gauge 的输出作为介绍,其它种类度量的输出,读者可查阅相关文档或者阅读 Metrics 源码。

    private void logGauge(String name, Gauge gauge) {
        loggerProxy.log(marker, "type=GAUGE, name={}, value={}", prefix(name), gauge.getValue());
    }

3、LoggerProxy

         Slf4jReporter的日志输出依赖于LoggerProxy,根据LoggerProxy的类名,我们知道这是一个有关日志输出的代理类,其实现如下:
    /* private class to allow logger configuration */
    static abstract class LoggerProxy {
        protected final Logger logger;

        public LoggerProxy(Logger logger) {
            this.logger = logger;
        }

        abstract void log(Marker marker, String format, Object... arguments);

        abstract boolean isEnabled(Marker marker);
    }

可以看到LoggerProxy实际上不过是代理了org.slf4j.Logger接口对日志输出。

ScheduledReporter

ScheduledReporter是ConsoleReporter、CsvReporter、Slf4jReporter及GraphiteReporter的共同父类,ScheduledReporter中的很多方法被子类所共用。

1、start

         功能描述:启动度量输出工作,实质为定时器不断地调用report方法输出。
    public void start(long period, TimeUnit unit) {
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    report();
                } catch (RuntimeException ex) {
                    LOG.error("RuntimeException thrown from {}#report. Exception was suppressed.", ScheduledReporter.this.getClass().getSimpleName(), ex);
                }
            }
        }, period, period, unit);
    }

2、stop

         功能描述:停止度量输出工作,实质为停止定时器。
    public void stop() {
        executor.shutdown(); // Disable new tasks from being submitted
        try {
            // Wait a while for existing tasks to terminate
            if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
                executor.shutdownNow(); // Cancel currently executing tasks
                // Wait a while for tasks to respond to being cancelled
                if (!executor.awaitTermination(1, TimeUnit.SECONDS)) {
                    System.err.println(getClass().getSimpleName() + ": ScheduledExecutorService did not terminate");
                }
            }
        } catch (InterruptedException ie) {
            // (Re-)Cancel if current thread also interrupted
            executor.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }


关于Spark内核设计的艺术 架构设计与实现

经过近一年的准备,《 Spark内核设计的艺术 架构设计与实现 》一书现已出版发行,图书如图:


纸质版售卖链接如下:

电子版售卖链接如下:



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
6月前
|
存储 Prometheus Cloud Native
「译文」Grafana Loki 简要指南:关于标签您需要了解的一切
「译文」Grafana Loki 简要指南:关于标签您需要了解的一切
|
30天前
|
存储 自然语言处理 搜索推荐
大模型 Agent 概述
大模型Agent是基于大型预训练模型构建的智能体,具有强大的语言理解和生成能力,能完成多任务处理。其记忆功能包括短期记忆和长期记忆,支持上下文保持、知识积累、计划决策及内容创作,广泛应用于自然语言处理、问答系统、信息检索、辅助决策、教育、创意应用和客服等领域。
|
6月前
|
人工智能 自然语言处理 API
【LangChain系列】第三篇:Agent代理简介及实践
【5月更文挑战第17天】LangChain代理利用大型语言模型(LLM)作为推理引擎,结合各种工具和数据库,处理复杂任务和决策。这些代理能理解和生成人类语言,访问外部信息,并结合LLM进行推理。文章介绍了如何通过LangChain构建代理,包括集成DuckDuckGo搜索和维基百科,以及创建Python REPL工具执行编程任务。此外,还展示了如何构建自定义工具,如获取当前日期的示例,强调了LangChain的灵活性和可扩展性,为LLM的应用开辟了新途径。
444 0
|
存储 Prometheus 自然语言处理
听GPT 讲Prometheus源代码--promql/promdb
听GPT 讲Prometheus源代码--promql/promdb
135 0
|
机器学习/深度学习 运维 并行计算
PyTorch Python API详解大全(持续更新ing...)(下)
PyTorch Python API详解大全(持续更新ing...)(下)
PyTorch Python API详解大全(持续更新ing...)(下)
|
存储 机器学习/深度学习 自然语言处理
PyTorch Python API详解大全(持续更新ing...)(上)
PyTorch Python API详解大全(持续更新ing...)
PyTorch Python API详解大全(持续更新ing...)(上)
|
存储 数据采集 Prometheus
Prometheus原理简介
充分了解Prometheus原理
615 0
Prometheus原理简介
|
存储 监控 数据可视化
|
索引
【Elastic Engineering】Elasticsearch:如何在导入时忽略格式错误的数据
Elasticsearch:如何在导入时忽略格式错误的数据
400 0
|
JSON 数据格式
使用json通过telegraf生成metrics(摘自telegraf github文档)
版权声明:本文可能为博主原创文章,若标明出处可随便转载。 https://blog.
1546 0