/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.metrics.spi; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.metrics.ContextFactory; import org.apache.hadoop.metrics.MetricsContext; import org.apache.hadoop.metrics.MetricsException; import org.apache.hadoop.metrics.MetricsRecord; import org.apache.hadoop.metrics.MetricsUtil; import org.apache.hadoop.metrics.Updater; /** * @deprecated in favor of <code>org.apache.hadoop.metrics2</code> usage. */ @Deprecated @InterfaceAudience.Public @InterfaceStability.Evolving public class CompositeContext extends AbstractMetricsContext { private static final Log LOG = LogFactory.getLog(CompositeContext.class); private static final String ARITY_LABEL = "arity"; private static final String SUB_FMT = "%s.sub%d"; private final ArrayList<MetricsContext> subctxt = new ArrayList<MetricsContext>(); @InterfaceAudience.Private public CompositeContext() { } @InterfaceAudience.Private public void init(String contextName, ContextFactory factory) { super.init(contextName, factory); int nKids; try { String sKids = getAttribute(ARITY_LABEL); nKids = Integer.valueOf(sKids); } catch (Exception e) { LOG.error("Unable to initialize composite metric " + contextName + ": could not init arity", e); return; } for (int i = 0; i < nKids; ++i) { MetricsContext ctxt = MetricsUtil.getContext( String.format(SUB_FMT, contextName, i), contextName); if (null != ctxt) { subctxt.add(ctxt); } } } @InterfaceAudience.Private @Override public MetricsRecord newRecord(String recordName) { return (MetricsRecord) Proxy.newProxyInstance( MetricsRecord.class.getClassLoader(), new Class[] { MetricsRecord.class }, new MetricsRecordDelegator(recordName, subctxt)); } @InterfaceAudience.Private @Override protected void emitRecord(String contextName, String recordName, OutputRecord outRec) throws IOException { for (MetricsContext ctxt : subctxt) { try { ((AbstractMetricsContext)ctxt).emitRecord( contextName, recordName, outRec); if (contextName == null || recordName == null || outRec == null) { throw new IOException(contextName + ":" + recordName + ":" + outRec); } } catch (IOException e) { LOG.warn("emitRecord failed: " + ctxt.getContextName(), e); } } } @InterfaceAudience.Private @Override protected void flush() throws IOException { for (MetricsContext ctxt : subctxt) { try { ((AbstractMetricsContext)ctxt).flush(); } catch (IOException e) { LOG.warn("flush failed: " + ctxt.getContextName(), e); } } } @InterfaceAudience.Private @Override public void startMonitoring() throws IOException { for (MetricsContext ctxt : subctxt) { try { ctxt.startMonitoring(); } catch (IOException e) { LOG.warn("startMonitoring failed: " + ctxt.getContextName(), e); } } } @InterfaceAudience.Private @Override public void stopMonitoring() { for (MetricsContext ctxt : subctxt) { ctxt.stopMonitoring(); } } /** * Return true if all subcontexts are monitoring. */ @InterfaceAudience.Private @Override public boolean isMonitoring() { boolean ret = true; for (MetricsContext ctxt : subctxt) { ret &= ctxt.isMonitoring(); } return ret; } @InterfaceAudience.Private @Override public void close() { for (MetricsContext ctxt : subctxt) { ctxt.close(); } } @InterfaceAudience.Private @Override public void registerUpdater(Updater updater) { for (MetricsContext ctxt : subctxt) { ctxt.registerUpdater(updater); } } @InterfaceAudience.Private @Override public void unregisterUpdater(Updater updater) { for (MetricsContext ctxt : subctxt) { ctxt.unregisterUpdater(updater); } } private static class MetricsRecordDelegator implements InvocationHandler { private static final Method m_getRecordName = initMethod(); private static Method initMethod() { try { return MetricsRecord.class.getMethod("getRecordName", new Class[0]); } catch (Exception e) { throw new RuntimeException("Internal error", e); } } private final String recordName; private final ArrayList<MetricsRecord> subrecs; MetricsRecordDelegator(String recordName, ArrayList<MetricsContext> ctxts) { this.recordName = recordName; this.subrecs = new ArrayList<MetricsRecord>(ctxts.size()); for (MetricsContext ctxt : ctxts) { subrecs.add(ctxt.createRecord(recordName)); } } public Object invoke(Object p, Method m, Object[] args) throws Throwable { if (m_getRecordName.equals(m)) { return recordName; } assert Void.TYPE.equals(m.getReturnType()); for (MetricsRecord rec : subrecs) { m.invoke(rec, args); } return null; } } }