All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.amazonaws.metrics.AwsSdkMetrics Maven / Gradle / Ivy

Go to download

The Amazon Web Services SDK for Java provides Java APIs for building software on AWS' cost-effective, scalable, and reliable infrastructure products. The AWS Java SDK allows developers to code against APIs for all of Amazon's infrastructure web services (Amazon S3, Amazon EC2, Amazon SQS, Amazon Relational Database Service, Amazon AutoScaling, etc).

The newest version!
/*
 * Copyright 2010-2014 Amazon.com, Inc. or its affiliates. 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.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.amazonaws.metrics;
import static com.amazonaws.SDKGlobalConfiguration.DEFAULT_METRICS_SYSTEM_PROPERTY;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.logging.LogFactory;

import com.amazonaws.SDKGlobalConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.jmx.spi.SdkMBeanRegistry;
import com.amazonaws.regions.Regions;
import com.amazonaws.util.AWSRequestMetrics.Field;
import com.amazonaws.util.AWSServiceMetrics;

/**
 * Used to control the default AWS SDK metric collection system.
 * 

* The default metric collection of the Java AWS SDK is disabled by default. To * enable it, simply specify the system property * "com.amazonaws.sdk.enableDefaultMetrics" when starting up the JVM. * When the system property is specified, a default metric collector will be * started at the AWS SDK level. The default implementation uploads the * request/response metrics captured to Amazon CloudWatch using AWS credentials * obtained via the {@link DefaultAWSCredentialsProviderChain}. *

* For additional optional attributes that can be specified for the system * property, please read the javadoc of the individual fields of * this class for more details. *

* Instead of via system properties, the default AWS SDK metric collection can * also be enabled programmatically via {@link #enableDefaultMetrics()}. * Similarly, metric collection at the AWS SDK level can be disabled via * {@link #disableMetrics()}. *

* Clients who needs to fully customize the metric collection can implement the * SPI {@link MetricCollector}, and then replace the default AWS SDK * implementation of the collector via * {@link #setMetricCollector(MetricCollector)}. *

* Alternatively, for limited customization of the internal collector * implementation provided by the AWS SDK, one can extend the internal Amazon * CloudWatch metric collector. See the javadoc at * com.amazonaws.metrics.internal.cloudwatch.CloudWatchMetricConfig for more * details. */ public enum AwsSdkMetrics { ; public static final String DEFAULT_METRIC_NAMESPACE = "AWSSDK/Java"; private static final String MBEAN_OBJECT_NAME = "com.amazonaws.management:type=" + AwsSdkMetrics.class.getSimpleName(); /** * Used to enable the use of a single metric namespace for all levels of SDK * generated CloudWatch metrics such as JVM level, host level, etc. * *

     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=useSingleMetricNamespace
     * 
*/ public static final String USE_SINGLE_METRIC_NAMESPACE = "useSingleMetricNamespace"; /** * Used to exclude the generation of JVM metrics when the AWS SDK default * metrics is enabled. * By default, jvm metrics is included. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=excludeJvmMetrics
     * 
*/ public static final String EXCLUDE_MACHINE_METRICS = "excludeMachineMetrics"; /** * Used to generate per host level metrics when the AWS SDK default * metrics is enabled. * By default, per-host level metrics is excluded. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=includePerHostMetrics
     * 
*/ public static final String INCLUDE_PER_HOST_METRICS = "includePerHostMetrics"; /** * Used to specify an AWS credential property file. * By default, the {@link DefaultAWSCredentialsProviderChain} is used. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=credentialFile=/path/aws.properties
     * 
*/ public static final String AWS_CREDENTAIL_PROPERTIES_FILE= "credentialFile"; /** * Used to specify the Amazon CloudWatch region for metrics uploading purposes. * By default, metrics are uploaded to us-east-1. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=cloudwatchRegion=us-west-2
     * 
*/ public static final String CLOUDWATCH_REGION = "cloudwatchRegion"; /** * Used to specify the internal in-memory queue size for queuing metrics * data points. The default size is 1,000. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=metricQueueSize=1000
     * 
*/ public static final String METRIC_QUEUE_SIZE = "metricQueueSize"; /** * Used to specify the internal queue polling timeout in millisecond. * The default timeout is 1 minute, which is optimal for the default * CloudWatch implementation. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=getQueuePollTimeoutMilli=60000
     * 
*/ public static final String QUEUE_POLL_TIMEOUT_MILLI = "getQueuePollTimeoutMilli"; /** * Used to specify a custom metric name space. * The default name space is {@link #DEFAULT_METRIC_NAMESPACE}. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=metricNameSpace=MyNameSpace
     * 
*/ public static final String METRIC_NAME_SPACE = "metricNameSpace"; /** * Used to generate per JVM level metrics when the AWS SDK default * metrics is enabled. * By default, JVM level metrics are not generated. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=jvmMetricName=Tomcat1
     * 
*/ public static final String JVM_METRIC_NAME = "jvmMetricName"; /** * Used to explicitly specify the host name for metric purposes, instead of * detecting the host name via {@link InetAddress} when the AWS SDK default * metrics is enabled. Specifying the host name also has the side effecting * of enabling per host level metrics. * *
     * Example:
     *  -Dcom.amazonaws.sdk.enableDefaultMetrics=hostMetricName=MyHost
     * 
*/ public static final String HOST_METRIC_NAME = "hostMetricName"; private static final String DEFAULT_METRIC_COLLECTOR_FACTORY = "com.amazonaws.metrics.internal.cloudwatch.DefaultMetricCollectorFactory"; /** * True iff the system property {@link #DEFAULT_METRICS_SYSTEM_PROPERTY} has * been set; false otherwise. */ private static final boolean defaultMetricsEnabled; private static volatile AWSCredentialsProvider credentialProvider; /** * True if machine metrics is to be excluded; false otherwise. */ private static volatile boolean machineMetricsExcluded; /** * True if per-host metrics is to be included; false if per-host metrics is * to be excluded when {@link #hostMetricName} is not specified. In the * absence of {@link #hostMetricName}, the host name will be automatically * detected via {@link InetAddress}. */ private static volatile boolean perHostMetricsIncluded; private static volatile Regions region; private static volatile Integer metricQueueSize; private static volatile Long queuePollTimeoutMilli; private static volatile String metricNameSpace = DEFAULT_METRIC_NAMESPACE; private static volatile String credentialFile; /** * No JVM level metrics is generated if this field is set to null or blank. * Otherwise, the value in this field is used to compose the metric name * space. * * Example: *
    *
  1. If jvmMetricName="Tomcat1" and host-level metrics is disabled, the * metric name space will be something like: "AWSSDK/Java/Tomcat1".
  2. *
  3. If jvmMetricName="Tomcat1" and host-level metrics is enabled, the * metric name space will be something like: * "AWSSDK/Java/myhost.mycompany.com/Tomcat1".
  4. *
  5. If jvmMetricName="Tomcat1" and host-level metrics is enabled and the * metricNameSpace="MyNameSpace", the metric name space will be something * like: "MyNameSpace/myhost.mycompany.com/Tomcat1".
  6. *
*/ private static volatile String jvmMetricName; private static volatile String hostMetricName; /** * True if the same metric namespace is to be used for all levels (such as * JVM level, host-level, etc.) of AWS Cloudwatch Metrics for the Java SDK; * false otherwise. */ private static volatile boolean singleMetricNamespace; static { String defaultMetrics = System.getProperty(DEFAULT_METRICS_SYSTEM_PROPERTY); defaultMetricsEnabled = defaultMetrics != null; if (defaultMetricsEnabled) { String[] values = defaultMetrics.split(","); boolean excludeMachineMetrics = false; boolean includePerHostMetrics = false; boolean useSingleMetricNamespace = false; for (String s: values) { String part = s.trim(); if (!excludeMachineMetrics && EXCLUDE_MACHINE_METRICS.equals(part)) { excludeMachineMetrics = true; } else if (!includePerHostMetrics && INCLUDE_PER_HOST_METRICS.equals(part)) { includePerHostMetrics = true; } else if (!useSingleMetricNamespace && USE_SINGLE_METRIC_NAMESPACE.equals(part)) { useSingleMetricNamespace = true; } else { String[] pair = part.split("="); if (pair.length == 2) { String key = pair[0].trim(); String value = pair[1].trim(); try { if (AWS_CREDENTAIL_PROPERTIES_FILE.equals(key)) { setCredentialFile0(value); } else if (CLOUDWATCH_REGION.equals(key)) { region = Regions.fromName(value); } else if (METRIC_QUEUE_SIZE.equals(key)) { Integer i = new Integer(value); if (i.intValue() < 1) throw new IllegalArgumentException(METRIC_QUEUE_SIZE + " must be at least 1"); metricQueueSize = i; } else if (QUEUE_POLL_TIMEOUT_MILLI.equals(key)) { Long i = new Long(value); if (i.intValue() < 1000) throw new IllegalArgumentException(QUEUE_POLL_TIMEOUT_MILLI + " must be at least 1000"); queuePollTimeoutMilli = i; } else if (METRIC_NAME_SPACE.equals(key)) { metricNameSpace = value; } else if (JVM_METRIC_NAME.equals(key)) { jvmMetricName = value; } else if (HOST_METRIC_NAME.equals(key)) { hostMetricName = value; } else { LogFactory.getLog(AwsSdkMetrics.class).debug("Ignoring unrecognized parameter: " + part); } } catch (Exception e) { LogFactory.getLog(AwsSdkMetrics.class).debug("Ignoring failure", e); } } } } machineMetricsExcluded = excludeMachineMetrics; perHostMetricsIncluded = includePerHostMetrics; singleMetricNamespace = useSingleMetricNamespace; } } private static final MetricRegistry registry = new MetricRegistry(); private static volatile MetricCollector mc; /** * Used to disallow re-entrancy in enabling the default metric collection system. */ private static boolean dirtyEnabling; /** Exports AwsSdkMetrics for JMX access. */ static { try { registerMetricAdminMBean(); } catch(Exception ex) { LogFactory.getLog(AwsSdkMetrics.class).warn("", ex); } } /** * Returns true if the metric admin MBean is currently registered for JMX * access; false otherwise. */ public static boolean isMetricAdminMBeanRegistered() { SdkMBeanRegistry registry = SdkMBeanRegistry.Factory.getMBeanRegistry(); return registry.isMBeanRegistered(MBEAN_OBJECT_NAME); } /** * Registers the metric admin MBean for JMX access. * * @return true if the registeration succeeded; false otherwise. */ public static boolean registerMetricAdminMBean() { SdkMBeanRegistry registry = SdkMBeanRegistry.Factory.getMBeanRegistry(); return registry.registerMetricAdminMBean(MBEAN_OBJECT_NAME); } /** * Unregisters the metric admin MBean from JMX. * * @return true if the unregisteration succeeded; false otherwise. */ public static boolean unregisterMetricAdminMBean() { SdkMBeanRegistry registry = SdkMBeanRegistry.Factory.getMBeanRegistry(); return registry.unregisterMBean(MBEAN_OBJECT_NAME); } /** * Returns a non-null request metric collector for the SDK. If no custom * request metric collector has previously been specified via * {@link #setMetricCollector(MetricCollector)} and the * {@link SDKGlobalConfiguration#DEFAULT_METRICS_SYSTEM_PROPERTY} has been set, then this method * will initialize and return the default metric collector provided by the * AWS SDK on a best-attempt basis. */ public static T getRequestMetricCollector() { if (mc == null) { if (isDefaultMetricsEnabled()) enableDefaultMetrics(); } @SuppressWarnings("unchecked") T t = (T)(mc == null ? RequestMetricCollector.NONE : mc.getRequestMetricCollector()); return t; } public static T getServiceMetricCollector() { if (mc == null) { if (isDefaultMetricsEnabled()) enableDefaultMetrics(); } @SuppressWarnings("unchecked") T t = (T)(mc == null ? ServiceMetricCollector.NONE : mc.getServiceMetricCollector()); return t; } /** * This method should never be called by anyone except the JMX MBean used * for administrative purposes only. */ static MetricCollector getInternalMetricCollector() { return mc; } public static T getMetricCollector() { if (mc == null) { if (isDefaultMetricsEnabled()) enableDefaultMetrics(); } @SuppressWarnings("unchecked") T t = (T)(mc == null ? MetricCollector.NONE : mc); return t; } /** * Sets the metric collector to be used by the AWS SDK, and stop the * previously running collector used by the AWS SDK, if any. Note, however, * a request metric collector specified at the web service client level or * request level, if any, always takes precedence over the one specified at * the AWS SDK level. *

* Caller of this method is responsible for starting the new metric * collector specified as the input parameter. * * @param mc * the metric collector to be used by the AWS SDK; or * null if no metric collection is to be performed * at the AWS SDK level. * * @see RequestMetricCollector * @see RequestMetricCollector#NONE */ public static synchronized void setMetricCollector(MetricCollector mc) { MetricCollector old = AwsSdkMetrics.mc; AwsSdkMetrics.mc = mc; if (old != null) { old.stop(); } } /** * Used to set whether the machine metrics is to be excluded. * * @param excludeMachineMetrics true if machine metrics is to be excluded; * false otherwise. */ public static void setMachineMetricsExcluded(boolean excludeMachineMetrics) { AwsSdkMetrics.machineMetricsExcluded = excludeMachineMetrics; } /** * Used to set whether the per-host metrics is to be included. * * @param includePerHostMetrics true if per-host metrics is to be included; * false otherwise. */ public static void setPerHostMetricsIncluded(boolean includePerHostMetrics) { AwsSdkMetrics.perHostMetricsIncluded = includePerHostMetrics; } /** * Returns true if the system property * {@link SDKGlobalConfiguration#DEFAULT_METRICS_SYSTEM_PROPERTY} has been * set; false otherwise. */ public static boolean isDefaultMetricsEnabled() { return defaultMetricsEnabled; } /** * Returns true if a single metric name space is to be used for all * levels of SDK generated CloudWatch metrics, including JVM level, host * level, etc.; false otherwise. */ public static boolean isSingleMetricNamespace() { return singleMetricNamespace; } /** * Used to set whether a single metric name space is to be used for all * levels of SDK generated CloudWatch metrics, including JVM level, host * level, etc. * * @param singleMetricNamespace * true if single metric name is to be used; false otherwise. */ public static void setSingleMetricNamespace(boolean singleMetricNamespace) { AwsSdkMetrics.singleMetricNamespace = singleMetricNamespace; } /** * Returns true if metrics at the AWS SDK level is enabled; false * if disabled. */ public static boolean isMetricsEnabled() { MetricCollector mc = AwsSdkMetrics.mc; return mc != null && mc.isEnabled(); } /** * Returns true if machine metrics is to be excluded. */ public static boolean isMachineMetricExcluded() { return machineMetricsExcluded; } /** * Returns true if the per-host metrics flag has been set; false otherwise. */ public static boolean isPerHostMetricIncluded() { return perHostMetricsIncluded; } /** * Returns true if per-host metrics is enabled; false otherwise. */ public static boolean isPerHostMetricEnabled() { if (perHostMetricsIncluded) return true; String host = hostMetricName; host = host == null ? "" : host.trim(); return host.length() > 0; } /** * Starts the default AWS SDK metric collector, but * only if no metric collector is currently in use at the AWS SDK * level. * * @return true if the default AWS SDK metric collector has been * successfully started by this call; false otherwise. */ public static synchronized boolean enableDefaultMetrics() { if (mc == null || !mc.isEnabled()) { if (dirtyEnabling) { throw new IllegalStateException("Reentrancy is not allowed"); } dirtyEnabling = true; try { Class c = Class.forName(DEFAULT_METRIC_COLLECTOR_FACTORY); MetricCollector.Factory f = (MetricCollector.Factory)c.newInstance(); MetricCollector instance = f.getInstance(); if (instance != null) { setMetricCollector(instance); return true; } } catch (Exception e) { LogFactory.getLog(AwsSdkMetrics.class) .warn("Failed to enable the default metrics", e); } finally { dirtyEnabling = false; } } return false; } /** * Convenient method to disable the metric collector at the AWS SDK * level. */ public static void disableMetrics() { setMetricCollector(MetricCollector.NONE); } /** * Adds the given metric type to the registry of predefined metrics to be * captured at the AWS SDK level. * * @return true if the set of predefined metric types gets changed as a * result of the call */ public static boolean add(MetricType type) { return type == null ? false : registry.addMetricType(type); } /** * Adds the given metric types to the registry of predefined metrics to be * captured at the AWS SDK level. * * @return true if the set of predefined metric types gets changed as a * result of the call */ public static boolean addAll(Collection types) { return types == null || types.size() == 0 ? false : registry.addMetricTypes(types); } /** * Sets the given metric types to replace the registry of predefined metrics * to be captured at the AWS SDK level. */ public static void set(Collection types) { registry.setMetricTypes(types); } /** * Removes the given metric type from the registry of predefined metrics to * be captured at the AWS SDK level. * * @return true if the set of predefined metric types gets changed as a * result of the call */ public static boolean remove(MetricType type) { return type == null ? false : registry.removeMetricType(type); } /** * Returns an unmodifiable set of the current predefined metrics. */ public static Set getPredefinedMetrics() { return registry.predefinedMetrics(); } /** * Returns the credential provider for the default AWS SDK metric implementation. * This method is restricted to calls from the default AWS SDK metric implementation. * * @throws SecurityException if called outside the default AWS SDK metric implementation. */ public static AWSCredentialsProvider getCredentialProvider() { StackTraceElement[] e = Thread.currentThread().getStackTrace(); for (int i=0; i < e.length; i++) { if (e[i].getClassName().equals(DEFAULT_METRIC_COLLECTOR_FACTORY)) { return credentialProvider; } } SecurityException ex = new SecurityException(); LogFactory.getLog(AwsSdkMetrics.class).warn("Illegal attempt to access the credential provider", ex); throw ex; } /** * Sets the credential provider for the default AWS SDK metric * implementation; or null if the default is to be used. Calling this method * may result in the credential provider being different from the credential * file property. */ public static synchronized void setCredentialProvider( AWSCredentialsProvider provider) { credentialProvider = provider; } /** * Returns the region configured for the default AWS SDK metric collector; * or null if the default is to be used. */ public static Regions getRegion() { return region; } /** * Sets the region to be used for the default AWS SDK metric collector; * or null if the default is to be used. */ public static void setRegion(Regions region) { AwsSdkMetrics.region = region; } /** * Returns the last set AWS credential file, or null if there is none. */ public static String getCredentailFile() { return credentialFile; } /** * Sets the AWS credential file to be used for accessing Amazon CloudWatch. * Successfully calling this method would result in the AWS credential * provider to make use of the given credential file. */ public static void setCredentialFile(String filepath) throws FileNotFoundException, IOException { setCredentialFile0(filepath); } /** * Internal method to implement the {@link #setCredentialFile(String)}. */ private static void setCredentialFile0(String filepath) throws FileNotFoundException, IOException { final PropertiesCredentials cred = new PropertiesCredentials(new File(filepath)); synchronized(AwsSdkMetrics.class) { credentialProvider = new AWSCredentialsProvider() { @Override public void refresh() {} @Override public AWSCredentials getCredentials() { return cred; } }; AwsSdkMetrics.credentialFile = filepath; } } /** * Returns the internal metric queue size to be used for the default AWS SDK * metric collector; or null if the default is to be used. */ public static Integer getMetricQueueSize() { return metricQueueSize; } /** * Sets the metric queue size to be used for the default AWS SDK metric collector; * or null if the default is to be used. */ public static void setMetricQueueSize(Integer size) { metricQueueSize = size; } /** * Returns the internal metric queue timeout in millisecond to be used for * the default AWS SDK metric collector; or null if the default is to be * used. */ public static Long getQueuePollTimeoutMilli() { return queuePollTimeoutMilli; } /** * Sets the queue poll time in millisecond to be used for the default AWS * SDK metric collector; or null if the default is to be used. */ public static void setQueuePollTimeoutMilli(Long timeoutMilli) { queuePollTimeoutMilli = timeoutMilli; } /** * Returns the metric name space, which is never null or blank. */ public static String getMetricNameSpace() { return metricNameSpace; } /** * Sets the metric name space. * * @param metricNameSpace * metric name space which must neither be null or blank. * * @throws IllegalArgumentException * if the specified metric name space is either null or blank. */ public static void setMetricNameSpace(String metricNameSpace) { if (metricNameSpace == null || metricNameSpace.trim().length() == 0) throw new IllegalArgumentException(); AwsSdkMetrics.metricNameSpace = metricNameSpace; } /** * Returns the name of the JVM for generating per-JVM level metrics; * or null or blank if per-JVM level metrics are disabled. */ public static String getJvmMetricName() { return jvmMetricName; } /** * Sets the name of the JVM for generating per-JVM level metrics. * * @param jvmMetricName * name of the JVM for generating per-JVM level metrics; or null * or blank if per-JVM level metrics are to be disabled. */ public static void setJvmMetricName(String jvmMetricName) { AwsSdkMetrics.jvmMetricName = jvmMetricName; } /** * Returns the host name for generating per-host level metrics; or * null or blank if the host is to be automatically detected via * {@link InetAddress}. */ public static String getHostMetricName() { return hostMetricName; } /** * Sets the host name for generating per-host level metrics. * * @param hostMetricName * host name for generating per-host level metrics; or * null or blank if the host is to be automatically detected via * {@link InetAddress}. */ public static void setHostMetricName(String hostMetricName) { AwsSdkMetrics.hostMetricName = hostMetricName; } /** * Used as a registry for the predefined metrics to be captured by the * metric collector at the AWS SDK level. */ private static class MetricRegistry { private final Set metricTypes = new HashSet(); private volatile Set readOnly; MetricRegistry() { metricTypes.add(Field.ClientExecuteTime); metricTypes.add(Field.Exception); metricTypes.add(Field.HttpClientRetryCount); metricTypes.add(Field.HttpRequestTime); metricTypes.add(Field.RequestCount); // metricTypes.add(Field.RequestSigningTime); // metricTypes.add(Field.ResponseProcessingTime); metricTypes.add(Field.RetryCount); metricTypes.add(Field.HttpClientSendRequestTime); metricTypes.add(Field.HttpClientReceiveResponseTime); metricTypes.add(Field.HttpClientPoolAvailableCount); metricTypes.add(Field.HttpClientPoolLeasedCount); metricTypes.add(Field.HttpClientPoolPendingCount); metricTypes.add(AWSServiceMetrics.HttpClientGetConnectionTime); syncReadOnly(); } private void syncReadOnly() { readOnly = Collections.unmodifiableSet(new HashSet(metricTypes)); } public boolean addMetricType(MetricType type) { synchronized(metricTypes) { boolean added = metricTypes.add(type); if (added) syncReadOnly(); return added; } } public boolean addMetricTypes(Collection types) { synchronized(metricTypes) { boolean added = metricTypes.addAll(types); if (added) syncReadOnly(); return added; } } public void setMetricTypes(Collection types) { synchronized(metricTypes) { if (types == null || types.size() == 0) { if (metricTypes.size() == 0) return; if (types == null) types = Collections.emptyList(); } metricTypes.clear(); if (!addMetricTypes(types)) { syncReadOnly(); // avoid missing sync } } } public boolean removeMetricType(MetricType type) { synchronized(metricTypes) { boolean removed = metricTypes.remove(type); if (removed) syncReadOnly(); return removed; } } public Set predefinedMetrics() { return readOnly; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy