/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed 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 *******************************************************************************/ package org.ebayopensource.turmeric.runtime.common.impl.internal.monitoring; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.ebayopensource.turmeric.runtime.common.exceptions.ErrorDataFactory; import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceRuntimeException; import org.ebayopensource.turmeric.runtime.common.monitoring.MetricDef; import org.ebayopensource.turmeric.runtime.common.monitoring.MetricId; import org.ebayopensource.turmeric.runtime.common.monitoring.MetricsCollector; import org.ebayopensource.turmeric.runtime.common.monitoring.MonitoringLevel; import org.ebayopensource.turmeric.runtime.common.monitoring.value.MetricValueAggregator; import org.ebayopensource.turmeric.runtime.common.pipeline.MessageContext; import org.ebayopensource.turmeric.runtime.common.pipeline.MessageContextAccessor; import org.ebayopensource.turmeric.runtime.common.service.ServiceId; import org.ebayopensource.turmeric.runtime.errorlibrary.ErrorConstants; /** * @author wdeng * @author ichernyshev */ final class MetricsCollectorImpl extends MetricsCollector { private final static String UNKNOWN_SERVICE_NAME = "__Unknown__"; private final MetricsRegistryImpl m_registry; private final MetricsConfigManager m_configMgr; private Map<MetricId,MetricValueAggregatorImpl> m_valueById = new HashMap<MetricId,MetricValueAggregatorImpl>(); MetricsCollectorImpl(MetricsRegistryImpl registry) { m_registry = registry; m_configMgr = new MetricsConfigManager(registry.isClientSide()); } static void setClientInstance(MetricsCollectorImpl value) { MetricsCollector.setClientInstance(value); } static void setServerInstance(MetricsCollectorImpl value) { MetricsCollector.setServerInstance(value); } MetricsConfigManager getConfigManager() { return m_configMgr; } /** * Using a MetricId to find the corresponding MetricValue * and return it. If the value doesn't exist, it returns null. */ @Override public MetricValueAggregator getMetricValue(String metricName) { MessageContext ctx = MessageContextAccessor.getContext(); return getMetricValue(metricName, ctx); } @Override public MetricValueAggregator getMetricValue(String metricName, MessageContext ctx) { if (ctx == null) { return getMetricValue(metricName, UNKNOWN_SERVICE_NAME, null, "__Unknown__"); } ServiceId id = ctx.getServiceId(); return getMetricValue(metricName, id.getAdminName(), id.getServiceSubname(), ctx.getOperationName()); } @Override public MetricValueAggregator getMetricValue( String metricName, ServiceId svcId, String opName) { return getMetricValue(metricName, svcId.getAdminName(), svcId.getServiceSubname(), opName); } @SuppressWarnings("deprecation") @Override public MetricValueAggregator getMetricValue(String metricName, String adminName, String subname, String opName) { MetricId id = new MetricId(metricName, adminName, subname, opName); return getMetricValue(id); } /** * Using the ServiceId to find the corresponding MetricValue * and return it. If the value doesn't exist, create a new * MetricValueAggregator using the given value as the * initialization value. */ @Override public MetricValueAggregator getMetricValue(MetricId metricId) { /* * This returns the ServiceMetricValueAggregator * The caller is supposed to call update on the returned * aggregator, which also implements the MetricValue interface * User is not expected to directly update his own instance of * the MetricValue and hence the name updatableMetricValue * The update() calls on the returned aggregator delegates * to the corresponding update() call on the caller supplied * MetricValue */ // no need to synchronize, since we simply swap pointers during update MetricValueAggregator value = m_valueById.get(metricId); if (value != null) { return value; } MetricDef def = m_registry.findMetricDef(metricId); if (def == null) { // this could be because metric is not registered or // because service was not loaded, so we could not find QName throw new ServiceRuntimeException(ErrorDataFactory.createErrorData(ErrorConstants.SVC_METRICS_DEFINITION_NOT_REGISTERED, ErrorConstants.ERRORDOMAIN, new Object[] {metricId})); } return addToAggregatorMap(metricId, def); } private synchronized MetricValueAggregator addToAggregatorMap( MetricId metricId, MetricDef metricDef) { // re-check map within synchronized call MetricValueAggregatorImpl value = m_valueById.get(metricId); if (value != null) { return value; } // Commenting out following if block as becuase of this the Service Level Metrics // are logged with wrong service name. /*if (metricDef.getOperationName() == null) { // if we don't care about operation - try to reuse an existing aggregator // otherwise we will always create a new aggregator for each new MetricId value = findByMetricDef(metricDef); }*/ // no value to reuse, create a new one value = MetricValueAggregatorImpl.create(metricId, metricDef, this); // create new map and swap pointers Map<MetricId,MetricValueAggregatorImpl> newMap = new HashMap<MetricId,MetricValueAggregatorImpl>(m_valueById); newMap.put(metricId, value); m_valueById = newMap; return value; } /*private MetricValueAggregatorImpl findByMetricDef(MetricDef metricDef) { for (MetricValueAggregatorImpl m: m_valueById.values()) { if (m.getMetricDef() == metricDef) { return m; } } return null; }*/ /** * Resets All the metric value to its initial value. */ @Override public void reset() { // get a copy of map pointer before iterating Map<MetricId,MetricValueAggregatorImpl> valueById = m_valueById; for (MetricValueAggregatorImpl aggr: valueById.values()) { aggr.reset(); } } @Override public MonitoringLevel getMonitoringLevel(String adminName) { return m_configMgr.getMonitoringLevel(adminName); } /** * Gets all the metric aggregation values of the moment. */ @Override public List<MetricValueAggregator> getAllMetricValues() { // get a copy of map pointer before iterating Map<MetricId,MetricValueAggregatorImpl> valueById = m_valueById; int size = valueById.size(); List<MetricValueAggregator> result = new ArrayList<MetricValueAggregator>(size); for (MetricValueAggregator value: valueById.values()) { MetricValueAggregator copy = (MetricValueAggregator)value.deepCopy(true); result.add(copy); } return result; } /** * Removes the metric value aggregators from the map for the given metric id. The * MetricId can contain wildcard. In that case, multiple aggregators would be removed * * @param metricId */ synchronized void removeMetricValues(MetricDef metricDef) { Map<MetricId,MetricValueAggregatorImpl> newMap = new HashMap<MetricId,MetricValueAggregatorImpl>(m_valueById); for (Iterator<MetricValueAggregatorImpl> it=newMap.values().iterator(); it.hasNext();) { MetricValueAggregatorImpl value = it.next(); if (value.getMetricDef() == metricDef) { it.remove(); } } m_valueById = newMap; } @Override public synchronized void reset(String adminName) { Map<MetricId, MetricValueAggregatorImpl> valueById = m_valueById; for (MetricId metricId : valueById.keySet()) { if (metricId.getAdminName().equals(adminName)) { m_valueById.get(metricId).reset(); } } } }