View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   * http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  
21  package org.apache.hadoop.hbase.metrics;
22  
23  
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.ServiceLoader;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.hadoop.hbase.classification.InterfaceAudience;
31  import org.apache.hadoop.hbase.util.ReflectionUtils;
32  
33  @InterfaceAudience.Private
34  public class MetricRegistriesLoader {
35    private static final Log LOG = LogFactory.getLog(MetricRegistries.class);
36  
37    private static final String defaultClass
38        = "org.apache.hadoop.hbase.metrics.impl.MetricRegistriesImpl";
39  
40    /**
41     * Creates a {@link MetricRegistries} instance using the corresponding {@link MetricRegistries}
42     * available to {@link ServiceLoader} on the classpath. If no instance is found, then default
43     * implementation will be loaded.
44     * @return A {@link MetricRegistries} implementation.
45     */
46    public static MetricRegistries load() {
47      List<MetricRegistries> availableImplementations = getDefinedImplemantations();
48      return load(availableImplementations);
49    }
50  
51    /**
52     * Creates a {@link MetricRegistries} instance using the corresponding {@link MetricRegistries}
53     * available to {@link ServiceLoader} on the classpath. If no instance is found, then default
54     * implementation will be loaded.
55     * @return A {@link MetricRegistries} implementation.
56     */
57    static MetricRegistries load(List<MetricRegistries> availableImplementations) {
58  
59      if (availableImplementations.size() == 1) {
60        // One and only one instance -- what we want/expect
61        MetricRegistries impl = availableImplementations.get(0);
62        LOG.info("Loaded MetricRegistries " + impl.getClass());
63        return impl;
64      } else if (availableImplementations.isEmpty()) {
65        try {
66          return ReflectionUtils.newInstance((Class<MetricRegistries>)Class.forName(defaultClass));
67        } catch (ClassNotFoundException e) {
68          throw new RuntimeException(e);
69        }
70      } else {
71        // Tell the user they're doing something wrong, and choose the first impl.
72        StringBuilder sb = new StringBuilder();
73        for (MetricRegistries factory : availableImplementations) {
74          if (sb.length() > 0) {
75            sb.append(", ");
76          }
77          sb.append(factory.getClass());
78        }
79        LOG.warn("Found multiple MetricRegistries implementations: " + sb
80            + ". Using first found implementation: " + availableImplementations.get(0));
81        return availableImplementations.get(0);
82      }
83    }
84  
85    private static List<MetricRegistries> getDefinedImplemantations() {
86      ServiceLoader<MetricRegistries> loader = ServiceLoader.load(MetricRegistries.class);
87      List<MetricRegistries> availableFactories = new ArrayList<>();
88      for (MetricRegistries impl : loader) {
89        availableFactories.add(impl);
90      }
91      return availableFactories;
92    }
93  }