MetricsSystemImpl.register

DataNodeMetrics

Take DataNodeMetrics as an example, the type of DefaultMetricsSystem.instance() is MetricsSystemImpl. A Metrics class must has a MetricsRegistry field, or has @Metrics annotation.

  public static DataNodeMetrics create(Configuration conf, String dnName) {
    String sessionId = conf.get(DFSConfigKeys.DFS_METRICS_SESSION_ID_KEY);
    MetricsSystem ms = DefaultMetricsSystem.instance();
    JvmMetrics jm = JvmMetrics.create("DataNode", sessionId, ms);
    String name = "DataNodeActivity-"+ (dnName.isEmpty()
        ? "UndefinedDataNodeName"+ DFSUtil.getRandom().nextInt() 
            : dnName.replace(':', '-'));

    // Percentile measurement is off by default, by watching no intervals
    int[] intervals = 
        conf.getInts(DFSConfigKeys.DFS_METRICS_PERCENTILES_INTERVALS_KEY);

    return ms.register(name, null, new DataNodeMetrics(name, sessionId,
        intervals, jm));
  }

MetricsSystemImpl.register

At first, it instantiates a MetricsSourceBuilder, and bouid a source using the builder.

@Override public synchronized <T>
  T register(String name, String desc, T source) {
    MetricsSourceBuilder sb = MetricsAnnotations.newSourceBuilder(source);
    final MetricsSource s = sb.build();

MetricsAnnotations.newSourceBuilder

 public static MetricsSourceBuilder newSourceBuilder(Object source) {
    return new MetricsSourceBuilder(source,
        DefaultMetricsFactory.getAnnotatedMetricsFactory());
  }

DefaultMetricsFactory.getAnnotatedMetricsFactory

Returns a MutableMetricsFactory

  public static MutableMetricsFactory getAnnotatedMetricsFactory() {
    return INSTANCE.getInstance(MutableMetricsFactory.class);
  }

MetricsSourceBuilder

MetricsSourceBuilder(Object source, MutableMetricsFactory factory) {
    this.source = checkNotNull(source, "source");
    this.factory = checkNotNull(factory, "mutable metrics factory");
    Class<?> cls = source.getClass();
    registry = initRegistry(source);

    for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) {
      add(source, field);
    }
    for (Method method : ReflectionUtils.getDeclaredMethodsIncludingInherited(cls)) {
      add(source, method);
    }
  }

At first, it finds a field with type MetricsRegistry. And then, it finds a annotation of class. It is @Metrics(about="DataNode metrics", context="dfs") in this case.

private MetricsRegistry initRegistry(Object source) {
    Class<?> cls = source.getClass();
    MetricsRegistry r = null;
    // Get the registry if it already exists.
    for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) {
      if (field.getType() != MetricsRegistry.class) continue;
      try {
        field.setAccessible(true);
        r = (MetricsRegistry) field.get(source);
        hasRegistry = r != null;
        break;
      }
      catch (Exception e) {
        LOG.warn("Error accessing field "+ field, e);
        continue;
      }
    }
    // Create a new registry according to annotation
    for (Annotation annotation : cls.getAnnotations()) {
      if (annotation instanceof Metrics) {
        Metrics ma = (Metrics) annotation;
        info = factory.getInfo(cls, ma);
        if (r == null) {
          r = new MetricsRegistry(info);
        }
        r.setContext(ma.context());
      }
    }
    if (r == null) return new MetricsRegistry(cls.getSimpleName());
    return r;
  }

After find the registry, it calls add(source, field) to add every field, and add(source, method) to add every method.

  MetricsSourceBuilder(Object source, MutableMetricsFactory factory) {
    this.source = checkNotNull(source, "source");
    this.factory = checkNotNull(factory, "mutable metrics factory");
    Class<?> cls = source.getClass();
    registry = initRegistry(source);

    for (Field field : ReflectionUtils.getDeclaredFieldsIncludingInherited(cls)) {
      add(source, field);
    }
    for (Method method : ReflectionUtils.getDeclaredMethodsIncludingInherited(cls)) {
      add(source, method);
    }

MetricsSourceBuilder.add

to add a field, the field must has Metric annotation, and then calls factory.newForField to get a MutableMetric. At last, it calls field.set(source, mutable) to set value to the field.

private void add(Object source, Field field) {
    for (Annotation annotation : field.getAnnotations()) {
      if (!(annotation instanceof Metric)) continue;
      try {
        // skip fields already set
        field.setAccessible(true);
        if (field.get(source) != null) continue;
      }
      catch (Exception e) {
        LOG.warn("Error accessing field "+ field +" annotated with"+
                 annotation, e);
        continue;
      }
      MutableMetric mutable = factory.newForField(field, (Metric) annotation,
                                                  registry);
      if (mutable != null) {
        try {
          field.set(source, mutable);
          hasAtMetric = true;
        }
        catch (Exception e) {
          throw new MetricsException("Error setting field "+ field +
                                     " annotated with "+ annotation, e);
        }
      }
    }
  }

MutableMetricsFactory.newForField

MutableMetric newForField(Field field, Metric annotation,
                            MetricsRegistry registry) {
    if (LOG.isDebugEnabled()) {
      LOG.debug("field "+ field +" with annotation "+ annotation);
    }
    MetricsInfo info = getInfo(annotation, field);
    MutableMetric metric = newForField(field, annotation);
    if (metric != null) {
      registry.add(info.name(), metric);
      return metric;
    }
    final Class<?> cls = field.getType();
    if (cls == MutableCounterInt.class) {
      return registry.newCounter(info, 0);
    }
    if (cls == MutableCounterLong.class) {
      return registry.newCounter(info, 0L);
    }
    if (cls == MutableGaugeInt.class) {
      return registry.newGauge(info, 0);
    }
    if (cls == MutableGaugeLong.class) {
      return registry.newGauge(info, 0L);
    }
    if (cls == MutableRate.class) {
      return registry.newRate(info.name(), info.description(),
                              annotation.always());
    }
    if (cls == MutableRates.class) {
      return new MutableRates(registry);
    }
    if (cls == MutableStat.class) {
      return registry.newStat(info.name(), info.description(),
                              annotation.sampleName(), annotation.valueName(),
                              annotation.always());
    }
    throw new MetricsException("Unsupported metric field "+ field.getName() +
                               " of type "+ field.getType().getName());
  }

newCounter

Take newCounter as an example.

/**
   * Create a mutable integer counter
   * @param info  metadata of the metric
   * @param iVal  initial value
   * @return a new counter object
   */
  public synchronized MutableCounterInt newCounter(MetricsInfo info, int iVal) {
    checkMetricName(info.name());
    MutableCounterInt ret = new MutableCounterInt(info, iVal);
    metricsMap.put(info.name(), ret);
    return ret;
  }

registerSource

Register method calls registerSource, it instantiate MetricsSourceAdapter, and put it to map sources, and then calls sa.start.

  synchronized
  void registerSource(String name, String desc, MetricsSource source) {
    checkNotNull(config, "config");
    MetricsConfig conf = sourceConfigs.get(name);
    MetricsSourceAdapter sa = conf != null
        ? new MetricsSourceAdapter(prefix, name, desc, source,
                                   injectedTags, period, conf)
        : new MetricsSourceAdapter(prefix, name, desc, source,
          injectedTags, period, config.subset(SOURCE_KEY));
    sources.put(name, sa);
    sa.start();
    LOG.debug("Registered source "+ name);
  }

Method start calls startMBeans

startMBeans register it to jmx.

  synchronized void startMBeans() {
    if (mbeanName != null) {
      LOG.warn("MBean "+ name +" already initialized!");
      LOG.debug("Stacktrace: ", new Throwable());
      return;
    }
    mbeanName = MBeans.register(prefix, name, this);
    LOG.debug("MBean for source "+ name +" registered.");
  }
 MetricsSourceAdapter(String prefix, String name, String description,
                       MetricsSource source, Iterable<MetricsTag> injectedTags,
                       int period, MetricsConfig conf) {
    this(prefix, name, description, source, injectedTags,
         conf.getFilter(RECORD_FILTER_KEY),
         conf.getFilter(METRIC_FILTER_KEY),
         period + 1, // hack to avoid most of the "innocuous" races.
         conf.getBoolean(START_MBEANS_KEY, true));
  }

MetricsSourceBuilder.build

  public MetricsSource build() {
    if (source instanceof MetricsSource) {
      if (hasAtMetric && !hasRegistry) {
        throw new MetricsException("Hybrid metrics: registry required.");
      }
      return (MetricsSource) source;
    }
    else if (!hasAtMetric) {
      throw new MetricsException("No valid @Metric annotation found.");
    }
    return new MetricsSource() {
      @Override
      public void getMetrics(MetricsCollector builder, boolean all) {
        registry.snapshot(builder.addRecord(registry.info()), all);
      }
    };
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值