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  import com.google.common.annotations.VisibleForTesting;
34  
35  @InterfaceAudience.Private
36  public class MetricRegistriesLoader {
37    private static final Log LOG = LogFactory.getLog(MetricRegistries.class);
38  
39    private static final String defaultClass
40        = "org.apache.hadoop.hbase.metrics.impl.MetricRegistriesImpl";
41  
42    /**
43     * Creates a {@link MetricRegistries} instance using the corresponding {@link MetricRegistries}
44     * available to {@link ServiceLoader} on the classpath. If no instance is found, then default
45     * implementation will be loaded.
46     * @return A {@link MetricRegistries} implementation.
47     */
48    public static MetricRegistries load() {
49      List<MetricRegistries> availableImplementations = getDefinedImplemantations();
50      return load(availableImplementations);
51    }
52  
53    /**
54     * Creates a {@link MetricRegistries} instance using the corresponding {@link MetricRegistries}
55     * available to {@link ServiceLoader} on the classpath. If no instance is found, then default
56     * implementation will be loaded.
57     * @return A {@link MetricRegistries} implementation.
58     */
59    @VisibleForTesting
60    static MetricRegistries load(List<MetricRegistries> availableImplementations) {
61  
62      if (availableImplementations.size() == 1) {
63        // One and only one instance -- what we want/expect
64        MetricRegistries impl = availableImplementations.get(0);
65        LOG.info("Loaded MetricRegistries " + impl.getClass());
66        return impl;
67      } else if (availableImplementations.isEmpty()) {
68        try {
69          return ReflectionUtils.newInstance((Class<MetricRegistries>)Class.forName(defaultClass));
70        } catch (ClassNotFoundException e) {
71          throw new RuntimeException(e);
72        }
73      } else {
74        // Tell the user they're doing something wrong, and choose the first impl.
75        StringBuilder sb = new StringBuilder();
76        for (MetricRegistries factory : availableImplementations) {
77          if (sb.length() > 0) {
78            sb.append(", ");
79          }
80          sb.append(factory.getClass());
81        }
82        LOG.warn("Found multiple MetricRegistries implementations: " + sb
83            + ". Using first found implementation: " + availableImplementations.get(0));
84        return availableImplementations.get(0);
85      }
86    }
87  
88    private static List<MetricRegistries> getDefinedImplemantations() {
89      ServiceLoader<MetricRegistries> loader = ServiceLoader.load(MetricRegistries.class);
90      List<MetricRegistries> availableFactories = new ArrayList<>();
91      for (MetricRegistries impl : loader) {
92        availableFactories.add(impl);
93      }
94      return availableFactories;
95    }
96  }